Здравствуйте, гость ( Вход | Регистрация )

30 страниц V < 1 2 3 4 5 > »   
Ответить в эту темуОткрыть новую тему
> Разработка findcolor, findimage, Pure lua
sutra
сообщение 30.3.2021, 15:44
Сообщение #41


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Последовательно пишу заголовок. Перегружаю Пилот, инфо, перегружаю, маску. Потом всё в один файл - получил картинку 32 бита, 300х300. Всё дело в доступе. Ну и действительно единичка потеряна, должно быть 301х301.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 17:38
Сообщение #42


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Дарк, что-то я не понял как пользоваться твоим имиджем. Насколько я понимаю информация хранится в bitmap_address (по аналогии с bits). А как вытащить то?
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 17:38
Сообщение #43


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Значит так. Версия из активной разработки. Дальше функции нужно обязательно развернуть в тело финдколора - это существенно ускоряет работу. Но при этом вполне очевидно получается дикий свинарник, особенно если учесть необходимость дублирования циклов под каждый из типов поиска. Поэтому я прошу потестить именно в таком виде. В идеале было-бы что-нибудь типа теста, как я делал под color_deviation_тип_сравнения.
образец теста
Код

--log(ext.color_deviation_a(3302856, 56 *256*256 + 101 *256 + 200, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 44 *256*256 + 101 *256 + 200, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 45 *256*256 + 101 *256 + 200, 5) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_a(3302856, 55 *256*256 + 101 *256 + 200, 5) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_a(3302856, 50 *256*256 + 107 *256 + 200, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 50 *256*256 +  95 *256 + 200, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 50 *256*256 + 106 *256 + 200, 5) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_a(3302856, 50 *256*256 +  96 *256 + 200, 5) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_a(3302856, 50 *256*256 + 101 *256 + 206, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 50 *256*256 + 101 *256 + 194, 5) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_a(3302856, 50 *256*256 + 101 *256 + 205, 5) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_a(3302856, 50 *256*256 + 101 *256 + 195, 5) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_a(3302856, 50 *256*256 + 101 *256 + 200, 5) and "true  test: passed" or "false test: fail")
--log()
--log()
--log()
--log()
--
--log(ext.color_deviation_r(3302856, 56 *256*256 + 101 *256 + 200, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 44 *256*256 + 101 *256 + 200, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 45 *256*256 + 101 *256 + 200, 10) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_r(3302856, 55 *256*256 + 101 *256 + 200, 10) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_r(3302856, 50 *256*256 + 113 *256 + 200, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 50 *256*256 +  89 *256 + 200, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 50 *256*256 + 112 *256 + 200, 10) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_r(3302856, 50 *256*256 +  90 *256 + 200, 10) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_r(3302856, 50 *256*256 + 101 *256 + 221, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 50 *256*256 + 101 *256 + 179, 10) and "true  test: fail" or "false test: passed")
--log(ext.color_deviation_r(3302856, 50 *256*256 + 101 *256 + 180, 10) and "true  test: passed" or "false test: fail")
--log(ext.color_deviation_r(3302856, 50 *256*256 + 101 *256 + 220, 10) and "true  test: passed" or "false test: fail")
--log()
--log(ext.color_deviation_r(3302856, 50 *256*256 + 101 *256 + 200, 10) and "true  test: passed" or "false test: fail")
--log()
--log()
--log()
--log()

Ну т.е. оно тупо видно, если где-то сфейлило.

По части производительности однозначно стоит покопать internal.color_deviation_*, т.к. часть правок вроде бы ушла, но какая именно еще бы знать.

На данный момент код работает только с обязательным указанием deviation.
Метод поиска 1 вообще не тестил. Очень слабо представляю, как кто-то будет через get pix собирать картинку и ждать полчаса. Раньше были проблемы с ульимой и методом 2 - приходилось через get pix фигачить, но более этой проблемы в ультиме не наблюдаю, приложений которым нужен get pix я более не знаю.

По коду - все, что в ext массиве подразумевает импорт в пилот ну и соответственно работоспособность. Список с кратким описанием:
color_to_rgb - разделение на каналы
color_to_bgr - разделение на каналы
rgb_to_color - сбор каналов в код цвета
bgr_to_color - сбор каналов в код цвета
color_deviation_a - проверка точки на соотвествие цвета с абсолютным смещением оттенка
color_deviation_r - проверка точки на соотвествие цвета с отностиельным смещением оттенка
color_deviation_s - проверка точки на соотвествие цвета с затенением цвета
findcolor - поиск цвета

// небольшой оффтоп и почему получилось так, как оно получилось.
Собственно решил сделать что-то вроде пилотовского сравнение на дипазон цветовой. color_deviation_* это собственно то, что делалось (и отдаленно думалось про финдколр), когда появился sutra. Ну собственно отсюда и вся структура кода.

Сообщение отредактировал DarkMaster - 30.3.2021, 17:40


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 17:46
Сообщение #44


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



собственно код
Код
--lua

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 = {}

ext.wait           = {} -- блок дейстивий по ожиданию цвета/изображений/кликов/окон.
ext.wait.log       = 1  -- включить ввывод description в лог.
ext.wait.log_level = 2  -- уровень логирования для description.
ext.lg_level  = 1       -- уровень логирования. Для вывода сообщения должен быть больше или равен
                        -- заданному при вызове функции.
                        -- Если при вызове функции уровень не задан, то он считается равным 0.

function ext.lg(data, comment, level)
    if  (not level and ext.lg_level < 0) or (level and level < ext.lg_level) then
        return
    end
    if  comment ~= nil then
        log(comment)
    end

    local tab = ""
    local deep = 0

    local function show(data)
        -- Пишем в лог комментарий.
        deep = deep + 1 -- Уровень вложенности вызовов функции.

        if type(data) == "table"    then
            local element_counter = 0
            for k,v in pairs(data) do
                element_counter = element_counter + 1
                if  type (v) == "table" then
                    log(tab..'table: '..tostring(k))
                    tab = tab .. "    "
                    show(v)
                    tab = string.sub(tab, 1, -5)
                else
                    if     type(v) == "nil"       then v = "nil"
                    elseif type(v) == "string"    then v = '"' .. v .. '"'
                    elseif type(v) == "number"    then v = tostring(v)
                    elseif type(v) == "function"  then v = tostring(v)
                    elseif type(v) == "thread"    then v = tostring(v)
                    elseif type(v) == "userdata"  then v = "userdata"
                    elseif type(v) == "boolean"   then v = tostring(v)
                    elseif type(v) == "table"     then
                        log(tab..""..k.." = "..v or "nil")
                    else
                        v = "uknown data type"
                    end
                    log(tab..""..k.." = " .. v)
                end
            end
            log(tab.."".."Elements in table: " .. element_counter)
        else
            log('table is "' .. type(data) .. '" data type. Value: ' .. tostring(data))
        end
        
        --tab = ""
        --deep = 0
    end
    
    show(data)
end


ext.getimage = function(x1, y1, x2, y2, handle, abs_flag)
    if handle > 2 or handle == 0 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

internal.deleteimage_orig = deleteimage
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

-- Раскладывает код цвета на отдельные каналы.
ext.color_to_rgb = function(c)
    local r,g,b
    b = math.floor(c/65536)
    g = math.floor(c/256-b*256)
    r = c-b*256*256-g*256
    return r, g ,b
end

ext.color_to_bgr = function(c)
    local r,g,b
    b = math.floor(c/65536)
    g = math.floor(c/256-b*256)
    r = c-b*256*256-g*256
    return b, g, r
end

ext.rgb_to_color = function(r, g, b)
    return b*256*256 + g*256 + r
end

ext.bgr_to_color = function(b, g, r)
    return b*256*256 + g*256 + r
end

--   ВНИМАНИЕ ФИКС СТАНДАРТНОЙ ФУНКИИ
--   ОРИГИНАЛЬНАЯ ФУНКЦИЯ ПОЛНОСТЬЮ ЗАМЕНЕНА
colortorgb = ext.color_to_rgb

internal.color_deviation_parse = function(b1, g1, r1, b2, g2, r2)
    if type(b1) == "table" then
    
    else
    
    end

    if not g1 then
        g1 = b1
        r1 = b1
        b2 = b1
        g2 = b1
        r2 = b1
    elseif not b2 then
        b2 = b1
        g2 = g1
        r2 = r1
    else
        -- Ставим минимальные значения вначале, максимальные вконце.
        b1, g1, r1, b2, g2, r2 = b2, g2, r2, b1, g1, r1
    end
    return b1, g1, r1, b2, g2, r2
end

--[[==
internal.color_deviation_parse = function(c1, c2, b1, g1, r1, b2, g2, r2)
    if type(b1) == "table" then
        if type(g1) == "table" then
            b2 = g1[1]
            g2 = g1[2]
            r2 = g1[3]
        else
            r2 = b2
            g2 = r1
            b2 = g1
        end
        r1 = b1[3]
        g1 = b1[2]
        b1 = b1[1]
    elseif type(b2) == "table" then
        r2 = b2[3]
        g2 = b2[2]
        b2 = b2[1]
    elseif not g1 and not r1 and not b2 and not g2 and not r2 then
        g1 = b1
        r1 = b1
        b2 = b1
        g2 = b1
        r2 = b1
    end

    if not b2 and not g2 and not r2 then
        r2 = r1
        g2 = g1
        b2 = b1
    end
    
    local c1r, c1g, c1b
    c1b = math.floor(c1/65536)
    c1g = math.floor(c1/256-c1b*256)
    c1r = c1-c1b*256*256-c1g*256
    
    local c2r, c2g, c2b
    c2b = math.floor(c2/65536)
    c2g = math.floor(c2/256-c2b*256)
    c2r = c2-c2b*256*256-c2g*256
    
    
    return b1, g1, r1, b2, g2, r2, c1r, c1g, c1b, c2r, c2g, c2b
end
]]

internal.color_deviation_a = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
    if  c1r1 - b1 <= c2r and c1g1 - g1 <= c2g and c1b1 - r1 <= c2b and
        c1r2 + b2 >= c2r and c1g2 + g2 >= c2g and c1b2 + r2 >= c2b then
        return true
    else
        return false
    end
end

internal.color_deviation_r = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
    local r1d = math.ceil(c1r1 * r1 * 0.01)
    local g1d = math.ceil(c1g1 * g1 * 0.01)
    local b1d = math.ceil(c1b1 * b1 * 0.01)
    
    local r2d = math.ceil(c1r2 * r2 * 0.01)
    local g2d = math.ceil(c1g2 * g2 * 0.01)
    local b2d = math.ceil(c1b2 * b2 * 0.01)

    if  c1r1 - r1d <= c2r and c1g1 - g1d <= c2g and c1b1 - b1d <= c2b and
        c1r2 + r2d >= c2r and c1g2 + g2d >= c2g and c1b2 + b2d >= c2b then
        return true
    else
        return false
    end
end

internal.color_deviation_s = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, br1, rg1, gb1, br2, rg2, gb2)
    c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r = c1b1+1, c1g1+1, c1r1+1, c1b2+1, c1g2+1, c1r2+1, c2b+1, c2g+1, c2r+1

    local c1br1 = c1b1/c1r1
    local c1rg1 = c1r1/c1g1
    local c1gb1 = c1g1/c1b1
    
    local c1br2 = c1b2/c1r2
    local c1rg2 = c1r2/c1g2
    local c1gb2 = c1g2/c1b2    
    
    local br_d1 = c1br1 * br1 * 0.01
    local rg_d1 = c1rg1 * rg1 * 0.01
    local gb_d1 = c1gb1 * gb1 * 0.01
    
    local br_d2 = c1br2 * br2 * 0.01
    local rg_d2 = c1rg2 * rg2 * 0.01
    local gb_d2 = c1gb2 * gb2 * 0.01
    
    local c2br = c2b/c2r
    local c2rg = c2r/c2g
    local c2gb = c2g/c2b
    
    --[[
    log(
    "", c1b1, c1g1, c1r1, "\r\n",
        c1b2, c1g2, c1r2, "\r\n",
        c2b, c2g, c2r
    )
    
    log(
    "", c1br1, c1rg1, c1gb1, "\r\n",
        c1br2, c1rg2, c1gb2, "\r\n",
        c2br,  c2rg,  c2gb
    )
    
    log(
    "", c1br1 , br_d1 , c2br , c1rg1 , rg_d1 , c2rg , c1gb1 , gb_d1 , c2gb , "\r\n",
        c1br2 , br_d2 , c2br , c1rg2 , rg_d2 , c2rg , c1gb2 , gb_d2 , c2gb
    )
    log(
    "", tostring(c1br1 - br_d1 <= c2br) , tostring(c1rg1 - rg_d1 <= c2rg) , tostring(c1gb1 - gb_d1 <= c2gb) , "\r\n",
        tostring(c1br2 + br_d2 >= c2br) , tostring(c1rg2 + rg_d2 >= c2rg) , tostring(c1gb2 + gb_d2 >= c2gb)
    )
    
    log(
    "", c1br1 - br_d1 ,"<=", c2br , c1rg1 - rg_d1 ,"<=", c2rg , c1gb1 - gb_d1 ,"<=", c2gb , "\r\n",
        c1br2 + br_d2 ,">=", c2br , c1rg2 + rg_d2 ,">=", c2rg , c1gb2 + gb_d2 ,">=", c2gb
    
    )
    ]]

    if  c1br1 - br_d1 <= c2br and c1rg1 - rg_d1 <= c2rg and c1gb1 - gb_d1 <= c2gb and
        c1br2 + br_d2 >= c2br and c1rg2 + rg_d2 >= c2rg and c1gb2 + gb_d2 >= c2gb then
        return true
    else
        return false
    end
end

internal.color_deviation = function(compare_func, c1, c2, b1, g1, r1, b2, g2, r2)
    local b1, g1, r1, b2, g2, r2 = internal.color_deviation_parse(b1, g1, r1, b2, g2, r2)
    local c1b1, c1g1, c1r1 = ext.color_to_bgr(c1)
    local c1b2 = c1b1
    local c1g2 = c1g1
    local c1r2 = c1r1
    
    local c2b, c2g, c2r = ext.color_to_bgr(c2)
    --log(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
    return compare_func(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_a
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет1>, <цвет2>, <b, g, r>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет>, <цвет2>, <b1, g1, r1>, <b2[, g2[, r2]]>
-- Значения b1, g1, r1 считаются допустимыми в плюс.
-- Значения b2, g2, r2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_a = function(c1, c2, b1, g1, r1, b2, g2, r2)  
    return internal.color_deviation(internal.color_deviation_a, c1, c2, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_r
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Погрешность задется в
-- ПРОЦЕНТАХ от текущего значения канала,
-- с округлением в бОльшую сторону.
-- Например при цвете точки: 50 101 200 и погрешности
-- равной 10% допустимая погрешность составит:
-- 50*10%=5, 101*10%=10.1=11, 200*10%=20
-- 50 101 200 исходный цвет
-- 45  90 180 минимально допустимый
-- 55 112 220 максимально допустимый
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет1>, <цвет2>, <b, g, r>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет>, <цвет2>, <b1, g1, r1>, <b2[, g2[, r2]]>
-- Значения b1, g1, r1 считаются допустимыми в плюс.
-- Значения b2, g2, r2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_r = function(c1, c2, b1, g1, r1, b2, g2, r2)  
    return internal.color_deviation(internal.color_deviation_r, c1, c2, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_s
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Погрешность задется в
-- ПРОЦЕНТАХ от ОТНОШЕНИЯ каналов друг к другу,
-- с округлением в бОльшую сторону.
-- Например при цвете точки: 50 101 200 и погрешности
-- равной 10% допустимая погрешность составит:
-- 50*10%=5, 101*10%=10.1=11, 200*10%=20
-- 50 101 200 исходный цвет
-- 45  90 180 минимально допустимый
-- 55 112 220 максимально допустимый
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- br, rg, gb.
-- <цвет1>, <цвет2>, <br, rg, gb>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- br, rg, gb.
-- <цвет>, <цвет2>, <br1, rg1, gb1>, <br2[, rg2[, gb2]]>
-- Значения br1, rg1, gb1 считаются допустимыми в плюс.
-- Значения br2, rg2, gb2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_s = function(c1, c2, br1, rg1, gb1, br2, rg2, bg2)  
    return internal.color_deviation(internal.color_deviation_s, c1, c2, br1, rg1, gb1, br2, rg2, bg2)
end

internal.parse_channel_to_min_max = function(v)
        local min, max
        if v then
            min, max = string.match (v, "([0-9x]+)-*([0-9x]*)")
            min = tonumber(min)
            max = tonumber(max)
            if not max then max = min end              
        else
            min, max = 0, 255
        end
        return min, max
    end

internal.parse_split_color_to_min_max_bgr = function(c)
    c = type(c) == "table" and c or {c}
    if c.r or c.g or c.b then
        c = {c}
    end
    local cc = ffi.new("uint8_t["..#c.."][6]")
    --log(type(c,#c))
    for i = 1, #c do
        if type(c[i]) == "table" then
            cc[i][0],cc[i][3] = internal.parse_channel_to_min_max(c[i].b)
            cc[i][1],cc[i][4] = internal.parse_channel_to_min_max(c[i].g)
            cc[i][2],cc[i][5] = internal.parse_channel_to_min_max(c[i].r)
        else
            local c1, c2 = string.match (c[i], "([0-9x]+)-*([0-9x]*)")
            c1 = tonumber(c1)
            c2 = tonumber(c2)
            cc[i][0] = math.floor(c1/65536)
            cc[i][1] = math.floor(c1/256-cc[i][0]*256)
            cc[i][2] = c1-cc[i][0]*256*256-cc[i][1]*256
            if c2 then
                cc[i][3] = math.floor(c2/65536)
                cc[i][4] = math.floor(c2/256-cc[i][3]*256)
                cc[i][5] = c2-cc[i][3]*256*256-cc[i][4]*256
            else
                cc[i][3],cc[i][4],cc[i][5] = cc[i][0],cc[i][1],cc[i][2]
            end
        end
    end

    return cc
end

internal.findcolor_deviation_parse = function(v)
    if type(v) == "number" then
        if v > 0 then
            v = {v, v, v, v, v, v}
        else
            v = nil -- вырубаем обработку отклонений.
        end
    elseif type(v) == "table" then
        vv[i][0],vv[i][3] = internal.parse_channel_to_min_max(c[i].b)
        vv[i][1],vv[i][4] = internal.parse_channel_to_min_max(c[i].g)
        vv[i][2],vv[i][5] = internal.parse_channel_to_min_max(c[i].r)
    end
    return v[1], v[2], v[3], v[4], v[5], v[6]
end

--[====[ findcolor
-- Функция поиска цвета либо нескольких цветов,
-- с возможностью задать некоторые отклонения в оттенке.
-- Синтаксис:
-- result = findcolor(<x_start, y_start, x_end, y_end | table_crds>,
-- <color> [,method [,count [,deviaton [,deviation_type [,abs_flag]]]])
--
-- <x_start, y_start, x_end, y_end | table_crds>
-- Координтаы задаются в виде прямоугольной области
-- с указанием координаты левого верхнего угла
-- и правого нижнего угла.
-- Координаты могут быть заданы четырмя переменными:
-- x_start, y_start, x_end, y_end
-- либо массивом с аналогичной структурой данных:
-- {x_start, y_start, x_end, y_end}
-- Отсчет координат начинатся с 0, а не 1.
-- Т.е. для FullHD область поиска будет
-- 0, 0, 1919, 1079.
--
-- <color>
-- Цвета, которые непосредственно ищются.
-- Синтаксис списка цветов:
-- <color | {color_1 [,color_2 [,... [,color_N]]]}>
-- Допустимые форматы цвета:
-- < dec_hex_color | dec_hex_color_1-dec_hex_color_2 |
-- {[r=val_1] [,g=val_2] [,b=val_3]} | [{r="val_1-val_2"] [,g="val_3-val_4"] [,b="val_5-val_6"}] >
-- Форматы цветов можно кобинировать в рамках списка. Например:
-- 133972, 0x5060DD-0x5170DD, {r=10, g=0xFF, b=12-18}
--
-- [method]
-- Метод поиска. Значение по умолчанию: 2
-- 0/не задан     - Быстрый метод. Получить изображение всего экрана.
-- 1              - устаревший метод, используется для совместимости. Очень медленный.
--                  Для получения изображения всего экрана, а не окна используйте abs_flag.
-- 2              - надежный метод. Средняя скорость.
--                  Для получения изображения всего экрана, а не окна используйте abs_flag.
-- хендла_окна    - очень быстрый метод. Работает с перекрытыми окнами.
--                  Предпочтительно использовать именно его. Не работает с некоторыми приложениями.
--                  Для корректной работы может потребоваться задать хендл родительского окна.
-- адрес_картинки - Адрес изображения в формате bmp 24 бита.
--                  "my_image.bmp" - изображение рядом с exe пилота.
--                  "folder\\my_image.bmp" - изображение в папке folder рядом с exe пилота
--                  "\\my_image.bmp" - изображение в корне диска, на котором лежит пилот.
--                  [[d:\uopilot\images\my_image.bmp]] - абсолютный путь.
--                  Учтите, что при задании адресов в lua символ '\' необходимо удваивать,
--                  либо заменять на '/', либо брать весь адрес в двойные квадртные скобки.
-- адрес_памяти,  - Поиск в ранее полученном изображении по средством функции getimage()
-- высота_изобр,    Указывается адрес битовой маски, высота изображения, ширина и количество
-- ширина_изобр,    байт на каждую строку. Из-за выравнивания размер строки может быть
-- длина.           не кратным битности изображения. Данный параметр так же используется
--                  для определения формата битовой маски (24 бита либо 24 бита цвет + 8 резерв).
--
-- [count]
-- Количество искомых изображений. 0 | -1 - найти все.
--
-- [deviation]
-- Допустимые отклонения цвета.
-- Синтаксис:
-- deviation_general | {blue, green, red} |
-- {blue_bottom, green_bottom, red_bottom, blue_upper, green_upper, red_upper}
-- Отклонения цвета может быть задано одним числом на все каналы в + и в -,
-- либо на каждый канал отдельно,
-- либо на каждый канал отдельно и отдельно нижняя и верхняя граница канала.
--
-- [deviation_type]
-- Тип расчета допустимого отклонения цвета. Значение по умолчанию "r".
-- Возможные значения:
-- "a" - absolute. Абсолютное отклонение канала.
--       Например, при цвете 50 100 200 и абсолютном отклонении 10,
--       допустимый диапазон цветов будет равен 40-60, 90-110, 190-210
-- "r" - relative. Относительное отклонение, задается в процентах.
--       Например, при цвете 50 100 200 и относительном отклонении 10,
--       допустимый диапазон цветов будет равен 45-55 90-110 180-220.
--       Округление происход в сторону расширения диапазона.
--       Например, при значении канала 101 и допустимом отклонении 10%,
--       допустимыми значениями канала будут 101-11=90 101+11=112, т.е. 90-112.
-- "s" - shadow. Затемнение/осветление. Рассчитывается соотношение каналов, задается в процентах.
--       Данный метод может быть полезен, например, при смене суток в игре.
--       В рамках данного метода цвет 50 100 200 и цвет 25 50 100 - будут полностью идентичны.
--       Для указанных цветов: 200/50=4 50/100=0.5 100/200=0.5
--                             100/25=4  25/50=0.5  50/100=0.5
--       При допустимом отклонении в 10, будут считаться допустимыми соотношения каналов:
--       3.6-4.4 0.45-0.55 0.45-0.55
--
-- [abs_flag]
-- Флаг указывающий на то, что изображение должно быть получено не относительно с окна
-- к которому произведена привязка пилота через Ctrl+A или workwindow,
-- а относительно левого верхнего угла экрана.
-- Актуально для method 1, 2.]====]

ext.findcolor = function(x1, y1, x2, y2, c, method, count, deviation, deviation_type, abs_crds)
local t = os.clock()
    if  type(x1) == "table" then
        abs_crds       = count
        deviation_type = method
        deviation      = c
        count          = y2
        method         = x2
        c              = y1    
    end
--log(1, os.clock() - t)    
    c                  = type(c) == "table" and c or {c}
    method             = method or workwindow()
    deviation          = internal.findcolor_deviation_parse(deviation)
    deviation_type     = deviation_type or "r"
--log(2, os.clock() - t)    
    local compare_func
    if deviation_type == "r" then
        compare_func = internal.color_deviation_r
    elseif deviation_type == "a" then
        compare_func = internal.color_deviation_a
    elseif deviation_type == "s" then
        compare_func = internal.color_deviation_s
    end
--log(3, os.clock() - t)    

    local offset_x1, offset_y1, offset_y1, offset_y2 = 0, 0, 0, 0
    local a, w, h, l
    if type(method) == "table" then
        a, w, h, l = method[1], method[2], method[3], method[4]
    elseif type(method) == "number" then
        a, w, h, l = getimage (x1, y1, x2, y2, method, abs_crds) -- getimage игнорирует x2, y2
        offset_x2 = w -    math.min(x2+1, w)  -- getimage игнорирует x2, y2
        offset_y2 = h - math.min(y2+1, h)  -- getimage игнорирует x2, y2
        saveimage(a,"image\\check.bmp")
    elseif type(method) == "string" then
        a, w, h, l = loadimage (method)
        offset_x1 =     math.min(x1,   w)
        offset_y1 =     math.min(y1,   h)
        offset_x2 = w -    math.min(x2+1, w)
        offset_y2 = h - math.min(y2+1, h)
    end
--log(4, os.clock() - t)    
    if not a then
        log("capture failed")
        stop_script()
    end
    log(a, w, h, l)
    
    local cc = internal.parse_split_color_to_min_max_bgr(c)

    local d = ffi.new("uint8_t[6]")
    d[0], d[1], d[2], d[3], d[4], d[5] = internal.findcolor_deviation_parse(deviation, d)


    local t = os.clock()
    
    log(a + offset_y1*l, a+(h-offset_y2)*l-1, l)
    
    local r = {}
    if deviation then
        for i = a + offset_y1*l, a+(h-offset_y2)*l-1, l do
            local y = i
            --p = zp + pa[0] + i / 3
            --log(222, tostring(p))
            --stop_script()
            for i = i+offset_x1*3, i+l-offset_x2*3-1, 3 do
                for j = 1, #c do    
                
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], rmem("unsigned char*",i)[0],rmem("unsigned char*",i+1)[0],rmem("unsigned char*",i+2)[0], d[0], d[1], d[2], d[3], d[4], d[5])

                    --if  cc[j][0] - d[0] <= rmem("unsigned char*",i)[0] and cc[j][1] - d[1] <= rmem("unsigned char*",i)[1] and cc[j][2] - d[2] <= rmem("unsigned char*",i)[2] and
                     --   cc[j][3] + d[3] >= rmem("unsigned char*",i)[0] and cc[j][4] + d[4] >= rmem("unsigned char*",i)[1] and cc[j][5] + d[5] >= rmem("unsigned char*",i)[2] then
                    
                    --log((i-y)/3 + 1, (y-a)/l/3 + 1)
                    
                    if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], rmem("unsigned char*",i)[0],rmem("unsigned char*",i)[1],rmem("unsigned char*",i)[2], d[0], d[1], d[2], d[3], d[4], d[5]) then                    
                        r[#r+1] = {}
                        r[#r][1] = (i-y)/3
                        r[#r][2] = math.floor((y-a)/l)
                        r[#r][3] = cc[j][1]*256*256 + cc[j][2]*256 + cc[j][3]
                        r[#r][4] = cc[j][4]*256*256 + cc[j][5]*256 + cc[j][6]
                        --log(r[#r][1],r[#r][2])
                        if count == #r then
                            return r
                        end
                    end
                end
                --p = p + 1
            end
        end
    else
        for y = 1, w do
            for x = 1, h do
                for i = 1, #deviation do
                    
                    if deviation_func() then
                    
                    end
                end
            end
        end
    end




--[[
    local pa = ffi.new("unsigned int[1]",a)
--local zp = ffi.new("unsigned char *")
    local p  = ffi.new("unsigned char[3]")

    local p = ffi.new("unsigned char *")
    p = p+pa[0]

--log(a)
--log(222, tostring(p))
--stop_script()
--log(333, #c)
    
--log(7, os.clock() - t)

    --ext.lg(d)
    --end_script()
    
--log(333, #c)    

--log(8, os.clock() - t)
local t = os.clock()
--log(l)
    local r = {}
    if deviation then
        for i = 0, h*l-1, l do
            local y = i
            --p = zp + pa[0] + i / 3
            --log(222, tostring(p))
            --stop_script()
            for i = i, i+w*3-1, 3 do
                for j = 1, #c do    
                --log(i)
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[0], p[1], p[2], d[1], d[2], d[3], d[4], d[5], d[6])
                    --if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[0], p[1], p[2], d[1], d[2], d[3], d[4], d[5], d[6]) then
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[i], p[i+1], p[i+2], d[1], d[2], d[3], d[4], d[5], d[6])
                    if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[i], p[i+1], p[i+2], d[1], d[2], d[3], d[4], d[5], d[6]) then                    
                        r[#r+1] = {}
                        r[#r][1] = (i-y)/3 + 1
                        r[#r][2] = (y)/l + 1
                        r[#r][3] = cc[j][1]*256*256 + cc[j][2]*256 + cc[j][3]
                        r[#r][4] = cc[j][4]*256*256 + cc[j][5]*256 + cc[j][6]  
                        --log(r[#r][1],r[#r][2])
                    end
                end
                --p = p + 1
            end
        end
    else
        for y = 1, w do
            for x = 1, h do
                for i = 1, #deviation do
                    
                    if deviation_func() then
                    
                    end
                end
            end
        end
    end
]]
    
deleteimage = internal.deleteimage
speed = speed + os.clock() - t
catch = #r
    
    return r
end


return ext


Прежде чем писать багрепорты на color_deviation_s и соотвественно метод 's' рекомендую сначала взять калькулятор и посчитать допустимые смещения) не все там так нативно.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 17:47
Сообщение #45


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Ни хрена себе ты наворочал. Тут месяц надо разбираться. Попробую. А надо то было просто добраться до битовой маски. Да пихнуть бы в файл без извращений.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 17:47
Сообщение #46


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



ext.lg - перекочевало из другого скрипта, в рамках color.lua поставляться не будет, вероятно будет жить в другой бибилотечке. Это из моих загашников.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 18:16
Сообщение #47


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Конечно моё мнение субъективно. Но вот зачем вообще нужен deviation? В имидже понятно, а в колоре зачем? Можно абсолютно точно задать требуемый диапазон поиска. Ради совместимости со старым хламом?
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 18:19
Сообщение #48


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
В имидже понятно, а в колоре зачем?

Идейно это был изначально возврат к пилотовскому:
if x y color1 color2
потом в рамках унификации ушло в общие алготритмы колора. Переписывалось раз 10. Там кстати парсинг цвета на середине откатившийся( Поправить нужно.

Сообщение отредактировал DarkMaster - 30.3.2021, 18:20


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 18:34
Сообщение #49


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Может не доглядел (тогда ткни меня носом), но не нашёл поиска по RED-BLUE, RED-GREEN. Поиск по разности каналов куда как важнее deviation. Могу привести просто кучу примеров, когда это необходимо. Очень грубый пример, просто для понимания. Ну вот навёл прицел на мишень - прицел стал другим (обычно ярче) и, как правило, он легко ищется в обоих состояниях именно по разности между каналами.

Да и color не нужен. Тот же винд. А для совместимости проще сделать финд-олд.

У меня реализация именно такая, могу вызывать или как if findcolor (если нужно просто проверить) или b,k=findcolor (если нужно получить конкретные результаты)

Опять же сугубо лично моё субъективное мнение. Чем проще и элегантнее, тем лучше. Появились новые технологии - отказывайся от старых. Извозчиков оставим для туристов. А тащить за собой весь хлам совместимости - только ошибки и коллизии плодить.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 18:41
Сообщение #50


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



По разности каналов не делал. В достаточно большой мере метод 'r' подразумевает эту разность, равно, как и 's' в сочетании с некоторым диапазоном.
Цитата
Да и color не нужен.

Задач достаточно много. В частности я задолбался писать пачку ифов на диапазоны и переводить dec/hex, чтобы задать их. Ну и начал собственно этот момент фиксить. И тут остапа понесло)

Цитата
Появились новые технологии - отказывайся от старых.

попробуй использовать 'r'. Мне понарвилось =) Не знаю, как именно для твоих целей, но у меня очень хорошо отрабатывает. Ну и для меня это как раз во многом новая технология: вбил цвет, написал 5, 'r' и не паришься. Это проще, чем задавать каждый канал, а эффективность меня очень порадовала. На данный момент струтура такова, что добавить любой метод сравнения очень просто - для этого и есть набор функций сравнения. Загоням туда уже распарсенный диапазон, девиэйшн, делаем любую мамтематику, получаем результат. При этом так же не нужно обращать внимание на какие-либо размеры изображений, методы забора и т.д. Весь смысл в том, что в функцию сравнения прилетают уже коретные данные, обо всем остальном уже позаботились. Битовая маска перебирается только в рамках указанных координат(привет багам старого getimage и потеряным единичкам).


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 18:43
Сообщение #51


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Да я всё понимаю. Поэтому и не берусь претендовать на что-либо. Делаю всё чисто для себя. Просто ты просил мнение - НА получи. (IMG:style_emoticons/default/biggrin.gif)
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 18:43
Сообщение #52


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Если есть любые идеи, как оно должно быть - готов изменить/поправить. Единственная просьба - максимально конкретно объяснить свое вИдение.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 18:45
Сообщение #53


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Да, кстати. Что-то у меня не получилось сохранить картинку твоим имиджем. Что не так делаю? Кинь конкретный примерчик.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 18:54
Сообщение #54


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



поправлен парсиг color_deviation_*
Код
--lua

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 = {}

ext.wait           = {} -- блок дейстивий по ожиданию цвета/изображений/кликов/окон.
ext.wait.log       = 1  -- включить ввывод description в лог.
ext.wait.log_level = 2  -- уровень логирования для description.
ext.lg_level  = 1       -- уровень логирования. Для вывода сообщения должен быть больше или равен
                        -- заданному при вызове функции.
                        -- Если при вызове функции уровень не задан, то он считается равным 0.

function ext.lg(data, comment, level)
    if  (not level and ext.lg_level < 0) or (level and level < ext.lg_level) then
        return
    end
    if  comment ~= nil then
        log(comment)
    end

    local tab = ""
    local deep = 0

    local function show(data)
        -- Пишем в лог комментарий.
        deep = deep + 1 -- Уровень вложенности вызовов функции.

        if type(data) == "table"    then
            local element_counter = 0
            for k,v in pairs(data) do
                element_counter = element_counter + 1
                if  type (v) == "table" then
                    log(tab..'table: '..tostring(k))
                    tab = tab .. "    "
                    show(v)
                    tab = string.sub(tab, 1, -5)
                else
                    if     type(v) == "nil"       then v = "nil"
                    elseif type(v) == "string"    then v = '"' .. v .. '"'
                    elseif type(v) == "number"    then v = tostring(v)
                    elseif type(v) == "function"  then v = tostring(v)
                    elseif type(v) == "thread"    then v = tostring(v)
                    elseif type(v) == "userdata"  then v = "userdata"
                    elseif type(v) == "boolean"   then v = tostring(v)
                    elseif type(v) == "table"     then
                        log(tab..""..k.." = "..v or "nil")
                    else
                        v = "uknown data type"
                    end
                    log(tab..""..k.." = " .. v)
                end
            end
            log(tab.."".."Elements in table: " .. element_counter)
        else
            log('table is "' .. type(data) .. '" data type. Value: ' .. tostring(data))
        end
        
        --tab = ""
        --deep = 0
    end
    
    show(data)
end


ext.getimage = function(x1, y1, x2, y2, handle, abs_flag)
    if handle > 2 or handle == 0 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

internal.deleteimage_orig = deleteimage
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

-- Раскладывает код цвета на отдельные каналы.
ext.color_to_rgb = function(c)
    local r,g,b
    b = math.floor(c/65536)
    g = math.floor(c/256-b*256)
    r = c-b*256*256-g*256
    return r, g ,b
end

ext.color_to_bgr = function(c)
    local r,g,b
    b = math.floor(c/65536)
    g = math.floor(c/256-b*256)
    r = c-b*256*256-g*256
    return b, g, r
end

ext.rgb_to_color = function(r, g, b)
    return b*256*256 + g*256 + r
end

ext.bgr_to_color = function(b, g, r)
    return b*256*256 + g*256 + r
end

--   ВНИМАНИЕ ФИКС СТАНДАРТНОЙ ФУНКИИ
--   ОРИГИНАЛЬНАЯ ФУНКЦИЯ ПОЛНОСТЬЮ ЗАМЕНЕНА
colortorgb = ext.color_to_rgb

internal.color_deviation_parse = function(b1, g1, r1, b2, g2, r2)
    if type(b1) == "table" then
    
    else
    
    end

    if not g1 then
        g1 = b1
        r1 = b1
        b2 = b1
        g2 = b1
        r2 = b1
    elseif not b2 then
        b2 = b1
        g2 = g1
        r2 = r1
    else
        -- Ставим минимальные значения вначале, максимальные вконце.
        b1, g1, r1, b2, g2, r2 = b2, g2, r2, b1, g1, r1
    end
    return b1, g1, r1, b2, g2, r2
end

--[[==
internal.color_deviation_parse = function(c1, c2, b1, g1, r1, b2, g2, r2)
    if type(b1) == "table" then
        if type(g1) == "table" then
            b2 = g1[1]
            g2 = g1[2]
            r2 = g1[3]
        else
            r2 = b2
            g2 = r1
            b2 = g1
        end
        r1 = b1[3]
        g1 = b1[2]
        b1 = b1[1]
    elseif type(b2) == "table" then
        r2 = b2[3]
        g2 = b2[2]
        b2 = b2[1]
    elseif not g1 and not r1 and not b2 and not g2 and not r2 then
        g1 = b1
        r1 = b1
        b2 = b1
        g2 = b1
        r2 = b1
    end

    if not b2 and not g2 and not r2 then
        r2 = r1
        g2 = g1
        b2 = b1
    end
    
    local c1r, c1g, c1b
    c1b = math.floor(c1/65536)
    c1g = math.floor(c1/256-c1b*256)
    c1r = c1-c1b*256*256-c1g*256
    
    local c2r, c2g, c2b
    c2b = math.floor(c2/65536)
    c2g = math.floor(c2/256-c2b*256)
    c2r = c2-c2b*256*256-c2g*256
    
    
    return b1, g1, r1, b2, g2, r2, c1r, c1g, c1b, c2r, c2g, c2b
end
]]

internal.color_deviation_a = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
    if  c1r1 - b1 <= c2r and c1g1 - g1 <= c2g and c1b1 - r1 <= c2b and
        c1r2 + b2 >= c2r and c1g2 + g2 >= c2g and c1b2 + r2 >= c2b then
        return true
    else
        return false
    end
end

internal.color_deviation_r = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
    local r1d = math.ceil(c1r1 * r1 * 0.01)
    local g1d = math.ceil(c1g1 * g1 * 0.01)
    local b1d = math.ceil(c1b1 * b1 * 0.01)
    
    local r2d = math.ceil(c1r2 * r2 * 0.01)
    local g2d = math.ceil(c1g2 * g2 * 0.01)
    local b2d = math.ceil(c1b2 * b2 * 0.01)

    if  c1r1 - r1d <= c2r and c1g1 - g1d <= c2g and c1b1 - b1d <= c2b and
        c1r2 + r2d >= c2r and c1g2 + g2d >= c2g and c1b2 + b2d >= c2b then
        return true
    else
        return false
    end
end

internal.color_deviation_s = function(c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r, br1, rg1, gb1, br2, rg2, gb2)
    c1b1, c1g1, c1r1, c1b2, c1g2, c1r2, c2b, c2g, c2r = c1b1+1, c1g1+1, c1r1+1, c1b2+1, c1g2+1, c1r2+1, c2b+1, c2g+1, c2r+1

    local c1br1 = c1b1/c1r1
    local c1rg1 = c1r1/c1g1
    local c1gb1 = c1g1/c1b1
    
    local c1br2 = c1b2/c1r2
    local c1rg2 = c1r2/c1g2
    local c1gb2 = c1g2/c1b2    
    
    local br_d1 = c1br1 * br1 * 0.01
    local rg_d1 = c1rg1 * rg1 * 0.01
    local gb_d1 = c1gb1 * gb1 * 0.01
    
    local br_d2 = c1br2 * br2 * 0.01
    local rg_d2 = c1rg2 * rg2 * 0.01
    local gb_d2 = c1gb2 * gb2 * 0.01
    
    local c2br = c2b/c2r
    local c2rg = c2r/c2g
    local c2gb = c2g/c2b
    
    --[[
    log(
    "", c1b1, c1g1, c1r1, "\r\n",
        c1b2, c1g2, c1r2, "\r\n",
        c2b, c2g, c2r
    )
    
    log(
    "", c1br1, c1rg1, c1gb1, "\r\n",
        c1br2, c1rg2, c1gb2, "\r\n",
        c2br,  c2rg,  c2gb
    )
    
    log(
    "", c1br1 , br_d1 , c2br , c1rg1 , rg_d1 , c2rg , c1gb1 , gb_d1 , c2gb , "\r\n",
        c1br2 , br_d2 , c2br , c1rg2 , rg_d2 , c2rg , c1gb2 , gb_d2 , c2gb
    )
    log(
    "", tostring(c1br1 - br_d1 <= c2br) , tostring(c1rg1 - rg_d1 <= c2rg) , tostring(c1gb1 - gb_d1 <= c2gb) , "\r\n",
        tostring(c1br2 + br_d2 >= c2br) , tostring(c1rg2 + rg_d2 >= c2rg) , tostring(c1gb2 + gb_d2 >= c2gb)
    )
    
    log(
    "", c1br1 - br_d1 ,"<=", c2br , c1rg1 - rg_d1 ,"<=", c2rg , c1gb1 - gb_d1 ,"<=", c2gb , "\r\n",
        c1br2 + br_d2 ,">=", c2br , c1rg2 + rg_d2 ,">=", c2rg , c1gb2 + gb_d2 ,">=", c2gb
    
    )
    ]]

    if  c1br1 - br_d1 <= c2br and c1rg1 - rg_d1 <= c2rg and c1gb1 - gb_d1 <= c2gb and
        c1br2 + br_d2 >= c2br and c1rg2 + rg_d2 >= c2rg and c1gb2 + gb_d2 >= c2gb then
        return true
    else
        return false
    end
end

internal.color_deviation = function(compare_func, c1, c2, b1, g1, r1, b2, g2, r2)
    local b1, g1, r1, b2, g2, r2 = internal.color_deviation_parse(b1, g1, r1, b2, g2, r2)
    local c2b, c2g, c2r = ext.color_to_bgr(c2)
    local cc = internal.parse_split_color_to_min_max_bgr(c1)

    return compare_func(cc[1][0], cc[1][1], cc[1][2], cc[1][3], cc[1][4], cc[1][5], c2b, c2g, c2r, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_a
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет1>, <цвет2>, <b, g, r>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет>, <цвет2>, <b1, g1, r1>, <b2[, g2[, r2]]>
-- Значения b1, g1, r1 считаются допустимыми в плюс.
-- Значения b2, g2, r2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_a = function(c1, c2, b1, g1, r1, b2, g2, r2)  
    return internal.color_deviation(internal.color_deviation_a, c1, c2, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_r
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Погрешность задется в
-- ПРОЦЕНТАХ от текущего значения канала,
-- с округлением в бОльшую сторону.
-- Например при цвете точки: 50 101 200 и погрешности
-- равной 10% допустимая погрешность составит:
-- 50*10%=5, 101*10%=10.1=11, 200*10%=20
-- 50 101 200 исходный цвет
-- 45  90 180 минимально допустимый
-- 55 112 220 максимально допустимый
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет1>, <цвет2>, <b, g, r>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- b, g, r.
-- <цвет>, <цвет2>, <b1, g1, r1>, <b2[, g2[, r2]]>
-- Значения b1, g1, r1 считаются допустимыми в плюс.
-- Значения b2, g2, r2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_r = function(c1, c2, b1, g1, r1, b2, g2, r2)  
    return internal.color_deviation(internal.color_deviation_r, c1, c2, b1, g1, r1, b2, g2, r2)
end

--[==[ color_deviation_s
-- Возвращает true, если результат
-- входит в допустимое отклонение цвета,
-- иначе вернет false.
-- Все цвета задаются в формате bgr, не rgb.
-- Пилот так же предоставляет цвета в формате bgr.
-- b, g, r в любом варианте могут быть заданы таблицей.
-- Погрешность задется в
-- ПРОЦЕНТАХ от ОТНОШЕНИЯ каналов друг к другу,
-- с округлением в бОльшую сторону.
-- Например при цвете точки: 50 101 200 и погрешности
-- равной 10% допустимая погрешность составит:
-- 50*10%=5, 101*10%=10.1=11, 200*10%=20
-- 50 101 200 исходный цвет
-- 45  90 180 минимально допустимый
-- 55 112 220 максимально допустимый
-- Допустимый синтаксис:
-- <цвет1>, <цвет2>, <value>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- br, rg, gb.
-- <цвет1>, <цвет2>, <br, rg, gb>
-- Значения допустимого отклонения
-- ситаются допустимыми +/- br, rg, gb.
-- <цвет>, <цвет2>, <br1, rg1, gb1>, <br2[, rg2[, gb2]]>
-- Значения br1, rg1, gb1 считаются допустимыми в плюс.
-- Значения br2, rg2, gb2 считаются допустимыми в минус.
-- Минус не пишется.]==]

ext.color_deviation_s = function(c1, c2, br1, rg1, gb1, br2, rg2, bg2)  
    return internal.color_deviation(internal.color_deviation_s, c1, c2, br1, rg1, gb1, br2, rg2, bg2)
end

internal.parse_channel_to_min_max = function(v)
        local min, max
        if v then
            min, max = string.match (v, "([0-9x]+)-*([0-9x]*)")
            min = tonumber(min)
            max = tonumber(max)
            if not max then max = min end              
        else
            min, max = 0, 255
        end
        return min, max
    end

internal.parse_split_color_to_min_max_bgr = function(c)
    c = type(c) == "table" and c or {c}
    if c.r or c.g or c.b then
        c = {c}
    end
    local cc = ffi.new("uint8_t["..#c.."][6]")
    --log(type(c,#c))
    for i = 1, #c do
        if type(c[i]) == "table" then
            cc[i][0],cc[i][3] = internal.parse_channel_to_min_max(c[i].b)
            cc[i][1],cc[i][4] = internal.parse_channel_to_min_max(c[i].g)
            cc[i][2],cc[i][5] = internal.parse_channel_to_min_max(c[i].r)
        else
            local c1, c2 = string.match (c[i], "([0-9x]+)-*([0-9x]*)")
            c1 = tonumber(c1)
            c2 = tonumber(c2)
            cc[i][0] = math.floor(c1/65536)
            cc[i][1] = math.floor(c1/256-cc[i][0]*256)
            cc[i][2] = c1-cc[i][0]*256*256-cc[i][1]*256
            if c2 then
                cc[i][3] = math.floor(c2/65536)
                cc[i][4] = math.floor(c2/256-cc[i][3]*256)
                cc[i][5] = c2-cc[i][3]*256*256-cc[i][4]*256
            else
                cc[i][3],cc[i][4],cc[i][5] = cc[i][0],cc[i][1],cc[i][2]
            end
        end
    end

    return cc
end

internal.findcolor_deviation_parse = function(v)
    if type(v) == "number" then
        if v > 0 then
            v = {v, v, v, v, v, v}
        else
            v = nil -- вырубаем обработку отклонений.
        end
    elseif type(v) == "table" then
        vv[i][0],vv[i][3] = internal.parse_channel_to_min_max(c[i].b)
        vv[i][1],vv[i][4] = internal.parse_channel_to_min_max(c[i].g)
        vv[i][2],vv[i][5] = internal.parse_channel_to_min_max(c[i].r)
    end
    return v[1], v[2], v[3], v[4], v[5], v[6]
end

--[====[ findcolor
-- Функция поиска цвета либо нескольких цветов,
-- с возможностью задать некоторые отклонения в оттенке.
-- Синтаксис:
-- result = findcolor(<x_start, y_start, x_end, y_end | table_crds>,
-- <color> [,method [,count [,deviaton [,deviation_type [,abs_flag]]]])
--
-- <x_start, y_start, x_end, y_end | table_crds>
-- Координтаы задаются в виде прямоугольной области
-- с указанием координаты левого верхнего угла
-- и правого нижнего угла.
-- Координаты могут быть заданы четырмя переменными:
-- x_start, y_start, x_end, y_end
-- либо массивом с аналогичной структурой данных:
-- {x_start, y_start, x_end, y_end}
-- Отсчет координат начинатся с 0, а не 1.
-- Т.е. для FullHD область поиска будет
-- 0, 0, 1919, 1079.
--
-- <color>
-- Цвета, которые непосредственно ищются.
-- Синтаксис списка цветов:
-- <color | {color_1 [,color_2 [,... [,color_N]]]}>
-- Допустимые форматы цвета:
-- < dec_hex_color | dec_hex_color_1-dec_hex_color_2 |
-- {[r=val_1] [,g=val_2] [,b=val_3]} | [{r="val_1-val_2"] [,g="val_3-val_4"] [,b="val_5-val_6"}] >
-- Форматы цветов можно кобинировать в рамках списка. Например:
-- 133972, 0x5060DD-0x5170DD, {r=10, g=0xFF, b=12-18}
--
-- [method]
-- Метод поиска. Значение по умолчанию: 2
-- 0/не задан     - Быстрый метод. Получить изображение всего экрана.
-- 1              - устаревший метод, используется для совместимости. Очень медленный.
--                  Для получения изображения всего экрана, а не окна используйте abs_flag.
-- 2              - надежный метод. Средняя скорость.
--                  Для получения изображения всего экрана, а не окна используйте abs_flag.
-- хендла_окна    - очень быстрый метод. Работает с перекрытыми окнами.
--                  Предпочтительно использовать именно его. Не работает с некоторыми приложениями.
--                  Для корректной работы может потребоваться задать хендл родительского окна.
-- адрес_картинки - Адрес изображения в формате bmp 24 бита.
--                  "my_image.bmp" - изображение рядом с exe пилота.
--                  "folder\\my_image.bmp" - изображение в папке folder рядом с exe пилота
--                  "\\my_image.bmp" - изображение в корне диска, на котором лежит пилот.
--                  [[d:\uopilot\images\my_image.bmp]] - абсолютный путь.
--                  Учтите, что при задании адресов в lua символ '\' необходимо удваивать,
--                  либо заменять на '/', либо брать весь адрес в двойные квадртные скобки.
-- адрес_памяти,  - Поиск в ранее полученном изображении по средством функции getimage()
-- высота_изобр,    Указывается адрес битовой маски, высота изображения, ширина и количество
-- ширина_изобр,    байт на каждую строку. Из-за выравнивания размер строки может быть
-- длина.           не кратным битности изображения. Данный параметр так же используется
--                  для определения формата битовой маски (24 бита либо 24 бита цвет + 8 резерв).
--
-- [count]
-- Количество искомых изображений. 0 | -1 - найти все.
--
-- [deviation]
-- Допустимые отклонения цвета.
-- Синтаксис:
-- deviation_general | {blue, green, red} |
-- {blue_bottom, green_bottom, red_bottom, blue_upper, green_upper, red_upper}
-- Отклонения цвета может быть задано одним числом на все каналы в + и в -,
-- либо на каждый канал отдельно,
-- либо на каждый канал отдельно и отдельно нижняя и верхняя граница канала.
--
-- [deviation_type]
-- Тип расчета допустимого отклонения цвета. Значение по умолчанию "r".
-- Возможные значения:
-- "a" - absolute. Абсолютное отклонение канала.
--       Например, при цвете 50 100 200 и абсолютном отклонении 10,
--       допустимый диапазон цветов будет равен 40-60, 90-110, 190-210
-- "r" - relative. Относительное отклонение, задается в процентах.
--       Например, при цвете 50 100 200 и относительном отклонении 10,
--       допустимый диапазон цветов будет равен 45-55 90-110 180-220.
--       Округление происход в сторону расширения диапазона.
--       Например, при значении канала 101 и допустимом отклонении 10%,
--       допустимыми значениями канала будут 101-11=90 101+11=112, т.е. 90-112.
-- "s" - shadow. Затемнение/осветление. Рассчитывается соотношение каналов, задается в процентах.
--       Данный метод может быть полезен, например, при смене суток в игре.
--       В рамках данного метода цвет 50 100 200 и цвет 25 50 100 - будут полностью идентичны.
--       Для указанных цветов: 200/50=4 50/100=0.5 100/200=0.5
--                             100/25=4  25/50=0.5  50/100=0.5
--       При допустимом отклонении в 10, будут считаться допустимыми соотношения каналов:
--       3.6-4.4 0.45-0.55 0.45-0.55
--
-- [abs_flag]
-- Флаг указывающий на то, что изображение должно быть получено не относительно с окна
-- к которому произведена привязка пилота через Ctrl+A или workwindow,
-- а относительно левого верхнего угла экрана.
-- Актуально для method 1, 2.]====]

ext.findcolor = function(x1, y1, x2, y2, c, method, count, deviation, deviation_type, abs_crds)
local t = os.clock()
    if  type(x1) == "table" then
        abs_crds       = count
        deviation_type = method
        deviation      = c
        count          = y2
        method         = x2
        c              = y1    
    end
--log(1, os.clock() - t)    
    c                  = type(c) == "table" and c or {c}
    method             = method or workwindow()
    deviation          = internal.findcolor_deviation_parse(deviation)
    deviation_type     = deviation_type or "r"
--log(2, os.clock() - t)    
    local compare_func
    if deviation_type == "r" then
        compare_func = internal.color_deviation_r
    elseif deviation_type == "a" then
        compare_func = internal.color_deviation_a
    elseif deviation_type == "s" then
        compare_func = internal.color_deviation_s
    end
--log(3, os.clock() - t)    

    local offset_x1, offset_y1, offset_y1, offset_y2 = 0, 0, 0, 0
    local a, w, h, l
    if type(method) == "table" then
        a, w, h, l = method[1], method[2], method[3], method[4]
    elseif type(method) == "number" then
        a, w, h, l = getimage (x1, y1, x2, y2, method, abs_crds) -- getimage игнорирует x2, y2
        offset_x2 = w -    math.min(x2+1, w)  -- getimage игнорирует x2, y2
        offset_y2 = h - math.min(y2+1, h)  -- getimage игнорирует x2, y2
        saveimage(a,"image\\check.bmp")
    elseif type(method) == "string" then
        a, w, h, l = loadimage (method)
        offset_x1 =     math.min(x1,   w)
        offset_y1 =     math.min(y1,   h)
        offset_x2 = w -    math.min(x2+1, w)
        offset_y2 = h - math.min(y2+1, h)
    end
--log(4, os.clock() - t)    
    if not a then
        log("capture failed")
        stop_script()
    end
    log(a, w, h, l)
    
    local cc = internal.parse_split_color_to_min_max_bgr(c)

    local d = ffi.new("uint8_t[6]")
    d[0], d[1], d[2], d[3], d[4], d[5] = internal.findcolor_deviation_parse(deviation, d)


    local t = os.clock()
    
    log(a + offset_y1*l, a+(h-offset_y2)*l-1, l)
    
    local r = {}
    if deviation then
        for i = a + offset_y1*l, a+(h-offset_y2)*l-1, l do
            local y = i
            --p = zp + pa[0] + i / 3
            --log(222, tostring(p))
            --stop_script()
            for i = i+offset_x1*3, i+l-offset_x2*3-1, 3 do
                for j = 1, #c do    
                
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], rmem("unsigned char*",i)[0],rmem("unsigned char*",i+1)[0],rmem("unsigned char*",i+2)[0], d[0], d[1], d[2], d[3], d[4], d[5])

                    --if  cc[j][0] - d[0] <= rmem("unsigned char*",i)[0] and cc[j][1] - d[1] <= rmem("unsigned char*",i)[1] and cc[j][2] - d[2] <= rmem("unsigned char*",i)[2] and
                     --   cc[j][3] + d[3] >= rmem("unsigned char*",i)[0] and cc[j][4] + d[4] >= rmem("unsigned char*",i)[1] and cc[j][5] + d[5] >= rmem("unsigned char*",i)[2] then
                    
                    --log((i-y)/3 + 1, (y-a)/l/3 + 1)
                    
                    if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], rmem("unsigned char*",i)[0],rmem("unsigned char*",i)[1],rmem("unsigned char*",i)[2], d[0], d[1], d[2], d[3], d[4], d[5]) then                    
                        r[#r+1] = {}
                        r[#r][1] = (i-y)/3
                        r[#r][2] = math.floor((y-a)/l)
                        r[#r][3] = cc[j][1]*256*256 + cc[j][2]*256 + cc[j][3]
                        r[#r][4] = cc[j][4]*256*256 + cc[j][5]*256 + cc[j][6]
                        --log(r[#r][1],r[#r][2])
                        if count == #r then
                            return r
                        end
                    end
                end
                --p = p + 1
            end
        end
    else
        for y = 1, w do
            for x = 1, h do
                for i = 1, #deviation do
                    
                    if deviation_func() then
                    
                    end
                end
            end
        end
    end




--[[
    local pa = ffi.new("unsigned int[1]",a)
--local zp = ffi.new("unsigned char *")
    local p  = ffi.new("unsigned char[3]")

    local p = ffi.new("unsigned char *")
    p = p+pa[0]

--log(a)
--log(222, tostring(p))
--stop_script()
--log(333, #c)
    
--log(7, os.clock() - t)

    --ext.lg(d)
    --end_script()
    
--log(333, #c)    

--log(8, os.clock() - t)
local t = os.clock()
--log(l)
    local r = {}
    if deviation then
        for i = 0, h*l-1, l do
            local y = i
            --p = zp + pa[0] + i / 3
            --log(222, tostring(p))
            --stop_script()
            for i = i, i+w*3-1, 3 do
                for j = 1, #c do    
                --log(i)
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[0], p[1], p[2], d[1], d[2], d[3], d[4], d[5], d[6])
                    --if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[0], p[1], p[2], d[1], d[2], d[3], d[4], d[5], d[6]) then
                    --log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[i], p[i+1], p[i+2], d[1], d[2], d[3], d[4], d[5], d[6])
                    if compare_func(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], p[i], p[i+1], p[i+2], d[1], d[2], d[3], d[4], d[5], d[6]) then                    
                        r[#r+1] = {}
                        r[#r][1] = (i-y)/3 + 1
                        r[#r][2] = (y)/l + 1
                        r[#r][3] = cc[j][1]*256*256 + cc[j][2]*256 + cc[j][3]
                        r[#r][4] = cc[j][4]*256*256 + cc[j][5]*256 + cc[j][6]  
                        --log(r[#r][1],r[#r][2])
                    end
                end
                --p = p + 1
            end
        end
    else
        for y = 1, w do
            for x = 1, h do
                for i = 1, #deviation do
                    
                    if deviation_func() then
                    
                    end
                end
            end
        end
    end
]]
    
deleteimage = internal.deleteimage
speed = speed + os.clock() - t
catch = #r
    
    return r
end


return ext


Цитата
Да, кстати. Что-то у меня не получилось сохранить картинку твоим имиджем. Что не так делаю? Кинь конкретный примерчик.

Дык я их и не сохранял =) Там где-то в отладке под старый getimage был saveimage. Скринилку пока не трогал.
Я тупо поставил в пеинте точки по углам и смотрел находит или нет (ну и в центре пару).

Если надо для отладки, то можно расскоментировать строку
--log(cc[j][0], cc[j][1], cc[j][2], cc[j][3], cc[j][4], cc[j][5], rmem("unsigned char*",i)[0],rmem("unsigned char*",i+1)[0],rmem("unsigned char*",i+2)[0], d[0], d[1], d[2], d[3], d[4], d[5])
Там покажет какие цвета передаются по каналам, какой цвет сравнивается, значения deviation.
Ну и можно еще расскоментить
--log(r[#r][1],r[#r][2])
будет при нахождении сразу показвать точки, но я для этого ext.lg обычно использовал. ext.lg - в лог пишет весь массив.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 20:15
Сообщение #55


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Вот объясните мне почему так? Просто хочу понять, чтобы быть в теме.

Дарк, у тебя отрицательное значение высоты:

local bi = ffi.new('BITMAPINFO', { {ffi.sizeof('BITMAPINFOHEADER'), w, -h, 1, 24, BI_RGB,0,0,0,0,0} })


А у первоисточника положительное:

local bi = ffi.new('BITMAPINFO', { {ffi.sizeof('BITMAPINFOHEADER'), x2-x, y2-y, 1, 32, BI_RGB,0,0,0,0,0} })
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 20:18
Сообщение #56


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Дарк, у тебя отрицательное значение высоты:

Это является флагом писать строки сверху-вниз или снизу-вверх. Вопрос по поводу гениальности данного решения к майкрософту. Для меня это быдло-код =)
// Сам на красивый качественный код не претендую, но стараюсь стать лучше)


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 20:22
Сообщение #57


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Спасибо, ну примерно так и подозревал. Плохо ничего не знать. (IMG:style_emoticons/default/sad.gif)
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 30.3.2021, 20:25
Сообщение #58


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Спасибо, ну примерно так и подозревал. Плохо ничего не знать.

Ну да, самое крутое не знать и писать. Думаешь я знал?) Cirus подсказал. А код он где-то нашел)) Зато как работает сарафанное радио "просвещение")) Один не знал, но подсказал, второй не знает и пишет, третий не знает и тестирует. Все прямо канонично.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
sutra
сообщение 30.3.2021, 20:30
Сообщение #59


*******

Adept
Сообщений: 923
Регистрация: 10.8.2018
Группа: Пользователи
Наличность: 0
Пользователь №: 19.007



Соответственно 32 битовая модель не требует контроля длины строки, правильно понимаю?

Ну в смысле кратности 4.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Madeus
сообщение 30.3.2021, 20:32
Сообщение #60


****

Apprentice
Сообщений: 282
Регистрация: 19.11.2019
Группа: Пользователи
Наличность: 8307
Пользователь №: 19.451
Возраст: 32



speed = speed + os.clock() - t

Лишняя строчка?)
Пользователь в онлайне!Delete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения

30 страниц V < 1 2 3 4 5 > » 
Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия | Версия для КПК Сейчас: 29.3.2024, 12:52
Designed by Nickostyle