[AI CC-CC2021] RECOLOR ENGINE v2 by S.H.

Станислав Хоффман

Участник
Топикстартер
Сообщения
277
Реакции
23
Всем привет.
Выкладываю свой скрипт "RECOLOR ENGINE v2", написанный год назад.

Автоматическое перекрашивание CMYK -> CMY в AI.

Сразу оговорюсь - работает только с заливками (FillColor), т.е. не работает с обводками - надо дописывать. Я разбивал все обводки и запускал скрипт.

В архиве 5 версий скрипта - отобраны самые рабочие, каждый даёт результат немного отличный от других. В архиве также лежит файл AI с тестами каждого скрипта.

ссылка: DropMeFiles – бесплатный файлообменник без регистрации
 

Станислав Хоффман

Участник
Топикстартер
Сообщения
277
Реакции
23
Потестировал на конкретных примерах, качество полученного преобразования не ахти (((
Действительно, если мало объектов то уж лучше всё ручками...
Примеры можно посмореть?
 

Станислав Хоффман

Участник
Топикстартер
Сообщения
277
Реакции
23
Квантовые эффекты однако. А если серьезно?
Честно говоря, понятия не имею, почему скрипт не может подбирать все цвета одинаково хорошо - он очень избирателен. Я потратил тогда много времени, чтобы во всём разобраться - пробовал разные цветовые модели(RGB, LAB, HSB), вводил корректирующие коэффициенты, ещё что-то. Подбор цвета идёт постепенно с каким-то шагом: +-0,5% или +-1% - в итоге вы получите разные цвета. Протестировав скрипт на одних цветах, я натыкался на проблемы при тестах с другими. Например, до сих пор осталась проблема с тёмно-синими - тёмно-фиолетовыми оттенками.
Можно ли довести скрипты до идеала? Приблизить можно, довести - нет. Меня результат вполне устроил, он вполне сопоставим с конвертацией в профиль в фотошоп.
 
Последнее редактирование:

splxgf

12 лет на форуме
Сообщения
7 740
Реакции
3 421
Гм, глянул код, наверное нужно dE прикрутить и итерациями подбираться к результату, а не перебором в цикле.
К примеру прикинуть шесть вариантов +/-2% по CMY, высчитать лучшее dE для Lab и двинуться в эту сторону. Если dE маленькое, то приближаться по 1%. Остановиться если dE на следующем шаге нельзя сделать лучше.
 

splxgf

12 лет на форуме
Сообщения
7 740
Реакции
3 421
Посмотри как работает код по мотивам первого варианта... с ошибками не боролся, интересно качество подбора.
Код:
var doc = app.activeDocument; 
var mSel = doc.selection;
var LL = new Array(6);
var AA = new Array(6);
var BB = new Array(6);
var DD = new Array(6);

function convertColor(src, dest, clrArr) 
{ 
    return app.convertSampleColor(ImageColorSpace[src], clrArr, ImageColorSpace[dest], ColorConvertPurpose.defaultpurpose); 
} 

function AddV(n,a){
    r=Math.round(n+a);
    if (r>100) {r=100}
    if (r<0) {r=0}
    return r;
}

function setval(lab,i,labs){
    LL[i]=lab[0];
    AA[i]=lab[1];
    BB[i]=lab[2];
    DD[i]=Math.sqrt(
    Math.pow(labs[0]-LL[i],2)+
    Math.pow(labs[1]-AA[i],2)+
    Math.pow(labs[2]-BB[i],2));
    return;
};

for (i=0; i < mSel.length; i++)
{

    if (mSel[i].filled == true)
    {

    var color = mSel[i].fillColor;

    var labs = convertColor("CMYK", "LAB", [
                    Math.round(color.cyan),
                    Math.round(color.magenta),
                    Math.round(color.yellow),
                    Math.round(color.black)]); 

    color.black = 0;

                    
                var goo = true;
                var maxDD=10000000000;
                while (goo){
                    goo=false;
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,1), AddV(color.magenta,0), AddV(color.yellow,0), 0]); 
                    setval(lab,0,labs);
                    if (maxDD>DD[0]){maxDD=DD[0]; goo=true; color.cyan=color.cyan+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,-1), AddV(color.magenta,0), AddV(color.yellow,0), 0]); 
                    setval(lab,1,labs);
                    if (maxDD>DD[1]){maxDD=DD[1]; goo=true; color.cyan=color.cyan-1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,1), AddV(color.yellow,0), 0]); 
                    setval(lab,2,labs);
                    if (maxDD>DD[2]){maxDD=DD[2]; goo=true; color.magenta=color.magenta+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,-1), AddV(color.yellow,0), 0]); 
                    setval(lab,3,labs);
                    if (maxDD>DD[3]){maxDD=DD[3]; goo=true; color.magenta=color.magenta-1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,0), AddV(color.yellow,1), 0]); 
                    setval(lab,4,labs);
                    if (maxDD>DD[4]){maxDD=DD[4]; goo=true; color.yellow=color.yellow+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,0), AddV(color.yellow,-1), 0]); 
                    setval(lab,5,labs);
                    if (maxDD>DD[5]){maxDD=DD[5]; goo=true; color.yellow=color.yellow-1}
                    
                }
}}
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Но ведь есть же еще, как это грустно звучит, полно вычметодов покоординатного спуска и т.д. Второй курс ВУЗа
 

Станислав Хоффман

Участник
Топикстартер
Сообщения
277
Реакции
23
Гм, глянул код, наверное нужно dE прикрутить и итерациями подбираться к результату, а не перебором в цикле.
К примеру прикинуть шесть вариантов +/-2% по CMY, высчитать лучшее dE для Lab и двинуться в эту сторону. Если dE маленькое, то приближаться по 1%. Остановиться если dE на следующем шаге нельзя сделать лучше.
Была, конечно, мысль прикрутить dE, но когда я посмотрел формулу её вычисления, понял, что это будет долго и сложно.
Я пошёл простым путём. Идея с нарастанием шага точности перебора тоже была - это грамотный подход. На тестах я этим пренебрёг для экономии кода - на стадии отладки чем меньше код, тем лучше. Это уже вопрос оптимизации скорости скрипта, но не точности.
 

Станислав Хоффман

Участник
Топикстартер
Сообщения
277
Реакции
23
Посмотри как работает код по мотивам первого варианта... с ошибками не боролся, интересно качество подбора.
Код:
var doc = app.activeDocument;
var mSel = doc.selection;
var LL = new Array(6);
var AA = new Array(6);
var BB = new Array(6);
var DD = new Array(6);

function convertColor(src, dest, clrArr)
{
    return app.convertSampleColor(ImageColorSpace[src], clrArr, ImageColorSpace[dest], ColorConvertPurpose.defaultpurpose);
}

function AddV(n,a){
    r=Math.round(n+a);
    if (r>100) {r=100}
    if (r<0) {r=0}
    return r;
}

function setval(lab,i,labs){
    LL[i]=lab[0];
    AA[i]=lab[1];
    BB[i]=lab[2];
    DD[i]=Math.sqrt(
    Math.pow(labs[0]-LL[i],2)+
    Math.pow(labs[1]-AA[i],2)+
    Math.pow(labs[2]-BB[i],2));
    return;
};

for (i=0; i < mSel.length; i++)
{

    if (mSel[i].filled == true)
    {

    var color = mSel[i].fillColor;

    var labs = convertColor("CMYK", "LAB", [
                    Math.round(color.cyan),
                    Math.round(color.magenta),
                    Math.round(color.yellow),
                    Math.round(color.black)]);

    color.black = 0;

                   
                var goo = true;
                var maxDD=10000000000;
                while (goo){
                    goo=false;
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,1), AddV(color.magenta,0), AddV(color.yellow,0), 0]);
                    setval(lab,0,labs);
                    if (maxDD>DD[0]){maxDD=DD[0]; goo=true; color.cyan=color.cyan+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,-1), AddV(color.magenta,0), AddV(color.yellow,0), 0]);
                    setval(lab,1,labs);
                    if (maxDD>DD[1]){maxDD=DD[1]; goo=true; color.cyan=color.cyan-1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,1), AddV(color.yellow,0), 0]);
                    setval(lab,2,labs);
                    if (maxDD>DD[2]){maxDD=DD[2]; goo=true; color.magenta=color.magenta+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,-1), AddV(color.yellow,0), 0]);
                    setval(lab,3,labs);
                    if (maxDD>DD[3]){maxDD=DD[3]; goo=true; color.magenta=color.magenta-1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,0), AddV(color.yellow,1), 0]);
                    setval(lab,4,labs);
                    if (maxDD>DD[4]){maxDD=DD[4]; goo=true; color.yellow=color.yellow+1}
                    var lab = convertColor("CMYK", "LAB", [AddV(color.cyan,0), AddV(color.magenta,0), AddV(color.yellow,-1), 0]);
                    setval(lab,5,labs);
                    if (maxDD>DD[5]){maxDD=DD[5]; goo=true; color.yellow=color.yellow-1}
                   
                }
}}
Напиши, пжлста, комментарии к коду. Я с функциями не особо дружу, программирование - хобби, начинаю разбираться в нём под конкретную задачу. В целом, красиво) Протестировать смогу в понедельник.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Я тоже
 

splxgf

12 лет на форуме
Сообщения
7 740
Реакции
3 421
А какие там комментарии нужны?
самая идея простая,
Находится Lab для исходного цвета и хранится в labs
Затем убирается черный в ноль и в цикле делаются попытки добавлять/отнимать по единичке к CMY.
AddV - добавляет по единичке к CMY и проверяет выход за диапазон 0..100.
setval находит dE между исходным labs и получившимся. (DD - вычисляется по cie76 году, там формула простая, корень из сумм квадратов разности).
Если delta E получилось улучшить, то сохраняем значение CMY в качестве текущего и текущую delta E в качестве максимальной.
if (maxDD>DD[4]){maxDD=DD[4]; goo=true; color.yellow=color.yellow+1}
Цикл делается до тех пор пока есть улучшения.
К сожалению протестировать не удалось, под рукой только CS5.5, а файл с примерами не pdf-compatable.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
Это както чересчур примитивно. А как же частные производные, вектор градиента? '))'
 

andrejK

R.I.P.
Сообщения
10 300
Реакции
5 218
@_MBK_, всё ты хочешь свести к задаче линейных уравнений)
нормальная реализация у @splxgf,
не чета хоффманской.


между прочим, в линейном программировании на целочисленных множествах -
почти так и работает алгоритм. перебором соседних точек.
 
Последнее редактирование:

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 138
Реакции
10 835
При чем тут линейные уравнения? Задача вовсе нелинейная, но таки классическая поиска многомерного экстремума, такие вовсю решали еще во времена когда компьютеры были большими и полумеханическими.
 

andrejK

R.I.P.
Сообщения
10 300
Реакции
5 218
@_MBK_, на целочисленных множествах алгоритма лучше перебора соседних точек - до сих пор не придумано)
никакие векторы там не работают
 

splxgf

12 лет на форуме
Сообщения
7 740
Реакции
3 421
поиска многомерного экстремума
В рамках моего понимания там только один экстремум, если бы был полноценный CMYK, тогда задача бы решалась другим способом.