3D.arxua.com
3D Графика » Уроки » Обрабатываем картинки средствами Photoshop и ExtendScript Toolkit
3D Графика » Уроки » Обрабатываем картинки средствами Photoshop и ExtendScript Toolkit

    Обрабатываем картинки средствами Photoshop и ExtendScript Toolkit


    Часто нам бывает надо сделать что-то с пачкой картинок. Есть несколько способов добиться этого:

    • используя ImageMagick – очень удобная консольная утилита, много чего умеющая
    • на The GIMP – там есть Scheme (диалект lisp-а) и Python
    • штатными средствами: PHP+gd / Powershell+System.Drawing / Python + PIL
    • в photoshop-е на JScript, VBScript или AppleScript

    Плюсы минусы последнего способа рассмотрим под катом. В качестве бонуса посмотрим на недокументированное API Photoshop-а.



    Нам понадобится

    • Adobe Photoshop CS5 (можно CS4)
    • Adobe ExtendScript Toolkit (входит в дистрибутив Photoshop)
    • Знание JScript
    • Несколько фоток

    Теория


    У Photoshop-а есть COM API, в котором покрыты многие из фотошоповских функций. Его, разумеется, можно использовать из JS- или VBS-скриптов. Adobe любезно предоставила разработчикам свою IDE, с автокопмлитом и брейкпоинтами. Поддерживаемые языки в ней JScript, VBScript (Win) и AppleScript (Mac). Я остановился на JScript, потому как большинству будет лучше всего понятен именно он.

    IDE


    Её зовут ExtendScript Toolkit. Вот она:ExtendScript Toolkit
    Что в ней меня поразило:

    • по умолчанию установлен не моноширинный шрифт, а какая-то дрянь. Тут же пофиксил
    • нет watch-ей. За это казнить надо. Их роль выполняет data browser и javascript console
    • по привычке нажал ctrl-D (копирует строчку в Решарпере) – и о чудо, оно работает!
    • там есть профайлинг
    • хелп есть, по контенту сносный, но до уровня msdn недотягивает.

    Скрпиты можно сохранить в формате jsx, при его открытии увидите вопрос: «запустить скрипт или редактировать?». 
    Приятно, что jsx можно компилировать (File → Export as binary), при этом будет создан файл с расширением jsxbin. Контент его будет примерно таким:

    @[email protected]@[email protected]

    Удобно, особенно если надо написать скрипт для фотошопа под заказ и не хочется давать исходники. Насчёт возможности его декомпиляции я детально не разбирался, но думаю, что переменные он меняет и кое-какую оптимизацию всё-таки делает. 
    Итак, IDE на первый взгляд неудобная, но поработав в ней минут 30, привыкаешь. 

    Скриптовый язык


    Начинается он с фразы

    #target photoshop

    Это обычный javascript с библиотеками Adobe. 
    Есть средства для работы с файловой системой, поддержка сокетов, reflection, XML. Класс Object есть.
    Для подключения к Photoshop-у существует глобальный объект app, ActiveXObject делать не надо. Активный документ в нём – app.activeDocumet. Функция alert показывает сообщение в Photoshop-е.
    При падении ошибки ничего не происходит, скрипт молча прекращает выполнение, как будто и не было его вовсе.
    Понравилось, как измерения (px, pt, cm, mm) конвертируются друг в друга:

    app.activeDocument.width.as("px");

    Т.к. ExtendScript кроссплатформенный, пути к файлам представляются как /d/Temp/…

    Живой пример


    Задача: в папке есть 100 файлов. Надо внедрить в каждый из них лого, которое есть в PSD-файле.
    Пример лого:
    logo example
    А вот и скрипт:


    #target photoshop
    app.bringToFront(); // запускаем Photoshop. Если он уже запущен, подключимся именно к нему, не к новому инстансу.
    var Constants = { /* определим кое-какие константы */ }
    ProcessDir(Constants.InputDir, Constants.OutputDir);
    function ProcessDir(dir, outDir) {
      var folder = Folder(dir); // Adobe-овский объект
      var files = folder.getFiles(Constants.FileMask); // Внимание, две маски через запятую (*.jpg,*.png) уже не работают.
      var outFolder = Folder(outDir);
      if (!outFolder.exists) {
        if (!outFolder.create()) {
          alert("Cannot create output folder");
          return; // может и не получиться
        }
      }
      var totalFiles = 0;
      for (var fileNum in files) {
         var outFile = GetOutputFileName(files[fileNum], outFolder.fullName); // куда писать результат
         AddLogoToFile(files[fileNum], outFile); // собственно, сама обработка
         totalFiles++;
      }
      alert(totalFiles + " files processed"); // увидит юзер в Photoshop-е в конце обработки
    }
    function AddLogoToFile(file, outputFile) {
      var photoFile = File(file); // Так открываются файлы, строчку open не понимает
      var logoFile = File(Constants.AddLogo.LogoPath);

      app.open(logoFile); // открываем лого
      app.activeDocument.artLayers["Text"].copy(); // ArtLayers – слои в файле. Этот слой назывался "Text"
      var logoWidth = app.activeDocument.width.as("px");
      var logoHeight = app.activeDocument.height.as("px");
      app.activeDocument.close();

      app.open(photoFile); // открываем фотку

      var width = app.activeDocument.width.as("px");
      var height = app.activeDocument.height.as("px");

      var logoLayer = app.activeDocument.artLayers.add(); // добавляем на фотку новый слой, куда поместим лого
      logoLayer.name = "Logo"; // название нового слоя

      app.activeDocument.paste(); // вставляем лого из clipboard

      var shape = [ // Photoshop вставляет всё в середину; выделяем лого, чтобы перенести его
        [(width - logoWidth) / 2, (height - logoHeight) / 2],
        [(width - logoWidth) / 2, (height + logoHeight) / 2],
        [(width + logoWidth) / 2, (height + logoHeight) / 2],
        [(width + logoWidth) / 2, (height - logoHeight) / 2]
      ];
      app.activeDocument.selection.select(shape);

      app.activeDocument.selection.translate( // переносим selection вправо вниз
        new UnitValue((width - logoWidth)/ 2, "px"),
        new UnitValue((height - logoHeight) / 2, "px"));

      var minImageDimension = Math.min(width, height); // масштабируем лого, чтобы оно было в 5 раз меньше минимального размера фотки
      var logoScaleMultiplier = minImageDimension / 5 / logoWidth * 100;
      app.activeDocument.selection.resize(logoScaleMultiplier, logoScaleMultiplier, AnchorPosition.BOTTOMRIGHT); // обратите внимание на последний аргумент

      app.activeDocument.selection.deselect();

      app.activeDocument.artLayers["Logo"].opacity = 75; // делаем слой полупрозрачным
      app.activeDocument.artLayers["Logo"].blendMode = BlendMode.LUMINOSITY; // устанавливаем режим смешивания, чтобы выглядело симпатичнее
      // а вот тут бы установить blending options! Об этом читайте дальше.
      SaveFile(outputFile); // сохранит и закроет файл
    }

    function SaveFile(outputFile) {
      var isPng = /png$/i.test(outputFile);
      var saveOptions;
      if (isPng) {
        saveOptions = new PNGSaveOptions();
      } else {
        saveOptions = new JPEGSaveOptions(); /* неинтересный код про качество картинки */
      }
      app.activeDocument.saveAs(File(outputFile), saveOptions, true, Extension.LOWERCASE) 
      app.activeDocument.close(SaveOptions.DONOTSAVECHANGES); // закрываем документ
    }

     


    Скрипт готов. Осталось сделать лого в формате PSD – такое, чтобы внутри был слой Text, на котором и должно быть размещено лого.


    О грустном


    Самое вкусное, что есть в Photoshop-е – blending options! А их-то в API как раз и нет. Есть copyLayerStyle, но она работает некорректно даже из GUI (вы можете это проверить, поиграв с параметрами drop shadow). Поэтому лого, конечно, мы вставить можем, но результат будет не сильно превосходить тот же ImageMagick.
    UPD: есть два способа быстро и легко применить стили из скрипта:

    • записав Action с этими настройками и выполнив его (спасибо за подсказку serge2)
    • сохранить стиль в preset-ах (используя кнопку «New Style» в диалоге «Blending Options»)

    Немного о недокументированном API


    Почитав доки (вы можете найти их в %ProgramFiles%Adobe\Adobe Photoshop CS5\Scripting\Documents\), мы узнаём, что оказывается, Photoshop умеет записывать действия пользователя. Для этого надо:

    1. Скопировать файл «ScriptListener.8li» из %ProgramFiles%Adobe\Adobe Photoshop CS5\Scripting\Utilities\ в %ProgramFiles%Adobe\Adobe Photoshop CS5\Plug-ins\Automate\
    2. (пере)запустить Photoshop
    3. Сделать то действие, о котором хочется узнать
    4. Найти на рабочем столе файлы ScriptListener.jsx и ScriptListener.vbs
    5. Не забыть удалить ScriptListener.8li (он тормозит работу Photoshop)

    В надежде заполучить код того, что мы ждали, открываем с рабочего стола ScriptListener.jsx. И тут нас ждёт сюрприз: в файле вот такой неюзабельный трэш:

    var idsetd = charIDToTypeID( "setd" );
      var desc15 = new ActionDescriptor();
      var idnull = charIDToTypeID( "null" );
        var ref6 = new ActionReference();
        var idPrpr = charIDToTypeID( "Prpr" );
        var idLefx = charIDToTypeID( "Lefx" );
        ref6.putProperty( idPrpr, idLefx );
        var idLyr = charIDToTypeID( "Lyr " );
        var idOrdn = charIDToTypeID( "Ordn" );
        var idTrgt = charIDToTypeID( "Trgt" );
        ref6.putEnumerated( idLyr, idOrdn, idTrgt );
      desc15.putReference( idnull, ref6 );
      var idT = charIDToTypeID( "T  " );
        var desc16 = new ActionDescriptor();
        var idScl = charIDToTypeID( "Scl " );
        var idPrc = charIDToTypeID( "#Prc" );
        desc16.putUnitDouble( idScl, idPrc, 100.000000 );
        var idDrSh = charIDToTypeID( "DrSh" );
          var desc17 = new ActionDescriptor();
          var idenab = charIDToTypeID( "enab" );
          desc17.putBoolean( idenab, true );
          var idMd = charIDToTypeID( "Md " );
          var idBlnM = charIDToTypeID( "BlnM" );
          var idMltp = charIDToTypeID( "Mltp" );
          desc17.putEnumerated( idMd, idBlnM, idMltp );
          var idClr = charIDToTypeID( "Clr " );
            var desc18 = new ActionDescriptor();
            var idRd = charIDToTypeID( "Rd " );
            desc18.putDouble( idRd, 0.000000 );
            var idGrn = charIDToTypeID( "Grn " );
            desc18.putDouble( idGrn, 0.000000 );
            var idBl = charIDToTypeID( "Bl " );
            desc18.putDouble( idBl, 0.000000 );
          var idRGBC = charIDToTypeID( "RGBC" );
          desc17.putObject( idClr, idRGBC, desc18 );
          var idOpct = charIDToTypeID( "Opct" );
          var idPrc = charIDToTypeID( "#Prc" );
          desc17.putUnitDouble( idOpct, idPrc, 75.000000 );
          var iduglg = charIDToTypeID( "uglg" );
          desc17.putBoolean( iduglg, true );
          var idlagl = charIDToTypeID( "lagl" );
          var idAng = charIDToTypeID( "#Ang" );
          desc17.putUnitDouble( idlagl, idAng, 120.000000 );
          var idDstn = charIDToTypeID( "Dstn" );
          var idPxl = charIDToTypeID( "#Pxl" );
          desc17.putUnitDouble( idDstn, idPxl, 5.000000 );
          var idCkmt = charIDToTypeID( "Ckmt" );
          var idPxl = charIDToTypeID( "#Pxl" );
          desc17.putUnitDouble( idCkmt, idPxl, 0.000000 );
          var idblur = charIDToTypeID( "blur" );
          var idPxl = charIDToTypeID( "#Pxl" );
          desc17.putUnitDouble( idblur, idPxl, 5.000000 );
          var idNose = charIDToTypeID( "Nose" );
          var idPrc = charIDToTypeID( "#Prc" );
          desc17.putUnitDouble( idNose, idPrc, 0.000000 );
          var idAntA = charIDToTypeID( "AntA" );
          desc17.putBoolean( idAntA, false );
          var idTrnS = charIDToTypeID( "TrnS" );
            var desc19 = new ActionDescriptor();
            var idNm = charIDToTypeID( "Nm " );
            desc19.putString( idNm, "Linear" );
          var idShpC = charIDToTypeID( "ShpC" );
          desc17.putObject( idTrnS, idShpC, desc19 );
          var idlayerConceals = stringIDToTypeID( "layerConceals" );
          desc17.putBoolean( idlayerConceals, true );
        var idDrSh = charIDToTypeID( "DrSh" );
        desc16.putObject( idDrSh, idDrSh, desc17 );
      var idLefx = charIDToTypeID( "Lefx" );
      desc15.putObject( idT, idLefx, desc16 );
    executeAction( idsetd, desc15, DialogModes.NO );

    Как вы думаете, что делает этот код? Он добавляет тень (Drop Shadow) к слою, это видно по название «DrSh». Я подозреваю, что внутри Photoshop-а прямо так и называются контролы в GUI.
    Но, выполнив этот код, обнаружим, что он работает.
    Можно найти, что executeAction может как показать диалог пользователю, так и сделать свою работу молча (это определяет последний параметр). Сами ID-шники нигде не описаны, о них (как и о том, что будет с ними в CS6) мы можем только гадать.
    Тем не менее, фича логгирования действий довольно интересная, если очень надо, можно по-быстрому накидать скриптик для себя.

    Ещё скрипты


    Заодно я написал вот такие функции:

    • ресайзинг картинок до определённого размера (ширина не больше X, высота не больше Y)
    • добавление рамок к картинкам – таких же, как в этом топике

    Если вам интересно, вы можете посмотреть их в том же скрипте наpastebin.

    Интересные факты

    • в API есть поддержка RAW. После того, как вы обработали RAW-файлы в Photoshop-е, сохранив в них настройки, вы можете быстро сконвертировать их в JPEG
    • в отличие от blending options, фильтры представлены в API довольно хорошо, для каждого из них есть функция
    • код в jsx-файлах можно вешать на события в Photoshop: например, при открытии файла добавлять в него новый слой, и так далее
    • API есть и для Illustrator, и для Bridge
    • из API есть доступ к гистограмме и к каналам

    Выводы


    API вкусное, очень вкусное. Но отсутствие поддержки blending options сильно удручает; если они нужны – будьте готовы к тому, что придётся возиться со страшным кодом. Если всё, что вам надо (что как раз и надо в большинстве случаев от пакетной обработки) – обвести картинку рамочкой, думаю, ImageMagick в этом случае будет быстрее и намного удобнее.

    + / -


    plus фильтры, гистограммы
    plus RAW
    plus color profiles, как в Photoshop-е
    plus javascript – удобный, понятный почти всем язык
    plus документация с примерами
    minus отсутствие blending options
    minus для работы нужен Photoshop /* внезапно */
    minus работает довольно медленно


    Источник: http://3d.arxua.com
    Наш партнер:

    Все самые свежие и актуальные отзывы о работодателях.

    Похожие новости
  • Vibrance vs Saturation Lightroom
  • Lightroom на iPad
  • Мебельная фурнитура
  • Digital -Tutors Principles of Photoshop CS
  • Добро пожаловать!
  • Информация

    Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.

Фото новости
Событие дня
Новые статьи
25 декабрь Сборник программ Portable от Sibiryaksoft v.24.12 (x86/64/2015/RUS/MULTi)

14 декабрь Adobe Illustrator CC 2015 (v19.2.0) Update 4 (2015/x86/x64/ENG/RUS)

13 декабрь SMPlayer 15.11.0 (2015/RUS/MULTi)

Топ новости

Обрабатываем картинки средствами Photoshop и ExtendScript Toolkit


Часто нам бывает надо сделать что-то с пачкой картинок. Есть несколько способов добиться этого:

Плюсы минусы последнего способа рассмотрим под катом. В качестве бонуса посмотрим на недокументированное API Photoshop-а.



Нам понадобится

Теория


У Photoshop-а есть COM API, в котором покрыты многие из фотошоповских функций. Его, разумеется, можно использовать из JS- или VBS-скриптов. Adobe любезно предоставила разработчикам свою IDE, с автокопмлитом и брейкпоинтами. Поддерживаемые языки в ней JScript, VBScript (Win) и AppleScript (Mac). Я остановился на JScript, потому как большинству будет лучше всего понятен именно он.

IDE


Её зовут ExtendScript Toolkit. Вот она:ExtendScript Toolkit
Что в ней меня поразило:

Скрпиты можно сохранить в формате jsx, при его открытии увидите вопрос: «запустить скрипт или редактировать?». 
Приятно, что jsx можно компилировать (File → Export as binary), при этом будет создан файл с расширением jsxbin. Контент его будет примерно таким:

@[email protected]@[email protected]

Удобно, особенно если надо написать скрипт для фотошопа под заказ и не хочется давать исходники. Насчёт возможности его декомпиляции я детально не разбирался, но думаю, что переменные он меняет и кое-какую оптимизацию всё-таки делает. 
Итак, IDE на первый взгляд неудобная, но поработав в ней минут 30, привыкаешь. 

Скриптовый язык


Начинается он с фразы

#target photoshop

Это обычный javascript с библиотеками Adobe. 
Есть средства для работы с файловой системой, поддержка сокетов, reflection, XML. Класс Object есть.
Для подключения к Photoshop-у существует глобальный объект app, ActiveXObject делать не надо. Активный документ в нём – app.activeDocumet. Функция alert показывает сообщение в Photoshop-е.
При падении ошибки ничего не происходит, скрипт молча прекращает выполнение, как будто и не было его вовсе.
Понравилось, как измерения (px, pt, cm, mm) конвертируются друг в друга:

app.activeDocument.width.as("px");

Т.к. ExtendScript кроссплатформенный, пути к файлам представляются как /d/Temp/…

Живой пример


Задача: в папке есть 100 файлов. Надо внедрить в каждый из них лого, которое есть в PSD-файле.
Пример лого:
logo example
А вот и скрипт:


#target photoshop
app.bringToFront(); // запускаем Photoshop. Если он уже запущен, подключимся именно к нему, не к новому инстансу.
var Constants = { /* определим кое-какие константы */ }
ProcessDir(Constants.InputDir, Constants.OutputDir);
function ProcessDir(dir, outDir) {
  var folder = Folder(dir); // Adobe-овский объект
  var files = folder.getFiles(Constants.FileMask); // Внимание, две маски через запятую (*.jpg,*.png) уже не работают.
  var outFolder = Folder(outDir);
  if (!outFolder.exists) {
    if (!outFolder.create()) {
      alert("Cannot create output folder");
      return; // может и не получиться
    }
  }
  var totalFiles = 0;
  for (var fileNum in files) {
     var outFile = GetOutputFileName(files[fileNum], outFolder.fullName); // куда писать результат
     AddLogoToFile(files[fileNum], outFile); // собственно, сама обработка
     totalFiles++;
  }
  alert(totalFiles + " files processed"); // увидит юзер в Photoshop-е в конце обработки
}
function AddLogoToFile(file, outputFile) {
  var photoFile = File(file); // Так открываются файлы, строчку open не понимает
  var logoFile = File(Constants.AddLogo.LogoPath);

  app.open(logoFile); // открываем лого
  app.activeDocument.artLayers["Text"].copy(); // ArtLayers – слои в файле. Этот слой назывался "Text"
  var logoWidth = app.activeDocument.width.as("px");
  var logoHeight = app.activeDocument.height.as("px");
  app.activeDocument.close();

  app.open(photoFile); // открываем фотку

  var width = app.activeDocument.width.as("px");
  var height = app.activeDocument.height.as("px");

  var logoLayer = app.activeDocument.artLayers.add(); // добавляем на фотку новый слой, куда поместим лого
  logoLayer.name = "Logo"; // название нового слоя

  app.activeDocument.paste(); // вставляем лого из clipboard

  var shape = [ // Photoshop вставляет всё в середину; выделяем лого, чтобы перенести его
    [(width - logoWidth) / 2, (height - logoHeight) / 2],
    [(width - logoWidth) / 2, (height + logoHeight) / 2],
    [(width + logoWidth) / 2, (height + logoHeight) / 2],
    [(width + logoWidth) / 2, (height - logoHeight) / 2]
  ];
  app.activeDocument.selection.select(shape);

  app.activeDocument.selection.translate( // переносим selection вправо вниз
    new UnitValue((width - logoWidth)/ 2, "px"),
    new UnitValue((height - logoHeight) / 2, "px"));

  var minImageDimension = Math.min(width, height); // масштабируем лого, чтобы оно было в 5 раз меньше минимального размера фотки
  var logoScaleMultiplier = minImageDimension / 5 / logoWidth * 100;
  app.activeDocument.selection.resize(logoScaleMultiplier, logoScaleMultiplier, AnchorPosition.BOTTOMRIGHT); // обратите внимание на последний аргумент

  app.activeDocument.selection.deselect();

  app.activeDocument.artLayers["Logo"].opacity = 75; // делаем слой полупрозрачным
  app.activeDocument.artLayers["Logo"].blendMode = BlendMode.LUMINOSITY; // устанавливаем режим смешивания, чтобы выглядело симпатичнее
  // а вот тут бы установить blending options! Об этом читайте дальше.
  SaveFile(outputFile); // сохранит и закроет файл
}

function SaveFile(outputFile) {
  var isPng = /png$/i.test(outputFile);
  var saveOptions;
  if (isPng) {
    saveOptions = new PNGSaveOptions();
  } else {
    saveOptions = new JPEGSaveOptions(); /* неинтересный код про качество картинки */
  }
  app.activeDocument.saveAs(File(outputFile), saveOptions, true, Extension.LOWERCASE) 
  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES); // закрываем документ
}

 


Скрипт готов. Осталось сделать лого в формате PSD – такое, чтобы внутри был слой Text, на котором и должно быть размещено лого.


О грустном


Самое вкусное, что есть в Photoshop-е – blending options! А их-то в API как раз и нет. Есть copyLayerStyle, но она работает некорректно даже из GUI (вы можете это проверить, поиграв с параметрами drop shadow). Поэтому лого, конечно, мы вставить можем, но результат будет не сильно превосходить тот же ImageMagick.
UPD: есть два способа быстро и легко применить стили из скрипта:

Немного о недокументированном API


Почитав доки (вы можете найти их в %ProgramFiles%Adobe\Adobe Photoshop CS5\Scripting\Documents\), мы узнаём, что оказывается, Photoshop умеет записывать действия пользователя. Для этого надо:

  1. Скопировать файл «ScriptListener.8li» из %ProgramFiles%Adobe\Adobe Photoshop CS5\Scripting\Utilities\ в %ProgramFiles%Adobe\Adobe Photoshop CS5\Plug-ins\Automate\
  2. (пере)запустить Photoshop
  3. Сделать то действие, о котором хочется узнать
  4. Найти на рабочем столе файлы ScriptListener.jsx и ScriptListener.vbs
  5. Не забыть удалить ScriptListener.8li (он тормозит работу Photoshop)

В надежде заполучить код того, что мы ждали, открываем с рабочего стола ScriptListener.jsx. И тут нас ждёт сюрприз: в файле вот такой неюзабельный трэш:

var idsetd = charIDToTypeID( "setd" );
  var desc15 = new ActionDescriptor();
  var idnull = charIDToTypeID( "null" );
    var ref6 = new ActionReference();
    var idPrpr = charIDToTypeID( "Prpr" );
    var idLefx = charIDToTypeID( "Lefx" );
    ref6.putProperty( idPrpr, idLefx );
    var idLyr = charIDToTypeID( "Lyr " );
    var idOrdn = charIDToTypeID( "Ordn" );
    var idTrgt = charIDToTypeID( "Trgt" );
    ref6.putEnumerated( idLyr, idOrdn, idTrgt );
  desc15.putReference( idnull, ref6 );
  var idT = charIDToTypeID( "T  " );
    var desc16 = new ActionDescriptor();
    var idScl = charIDToTypeID( "Scl " );
    var idPrc = charIDToTypeID( "#Prc" );
    desc16.putUnitDouble( idScl, idPrc, 100.000000 );
    var idDrSh = charIDToTypeID( "DrSh" );
      var desc17 = new ActionDescriptor();
      var idenab = charIDToTypeID( "enab" );
      desc17.putBoolean( idenab, true );
      var idMd = charIDToTypeID( "Md " );
      var idBlnM = charIDToTypeID( "BlnM" );
      var idMltp = charIDToTypeID( "Mltp" );
      desc17.putEnumerated( idMd, idBlnM, idMltp );
      var idClr = charIDToTypeID( "Clr " );
        var desc18 = new ActionDescriptor();
        var idRd = charIDToTypeID( "Rd " );
        desc18.putDouble( idRd, 0.000000 );
        var idGrn = charIDToTypeID( "Grn " );
        desc18.putDouble( idGrn, 0.000000 );
        var idBl = charIDToTypeID( "Bl " );
        desc18.putDouble( idBl, 0.000000 );
      var idRGBC = charIDToTypeID( "RGBC" );
      desc17.putObject( idClr, idRGBC, desc18 );
      var idOpct = charIDToTypeID( "Opct" );
      var idPrc = charIDToTypeID( "#Prc" );
      desc17.putUnitDouble( idOpct, idPrc, 75.000000 );
      var iduglg = charIDToTypeID( "uglg" );
      desc17.putBoolean( iduglg, true );
      var idlagl = charIDToTypeID( "lagl" );
      var idAng = charIDToTypeID( "#Ang" );
      desc17.putUnitDouble( idlagl, idAng, 120.000000 );
      var idDstn = charIDToTypeID( "Dstn" );
      var idPxl = charIDToTypeID( "#Pxl" );
      desc17.putUnitDouble( idDstn, idPxl, 5.000000 );
      var idCkmt = charIDToTypeID( "Ckmt" );
      var idPxl = charIDToTypeID( "#Pxl" );
      desc17.putUnitDouble( idCkmt, idPxl, 0.000000 );
      var idblur = charIDToTypeID( "blur" );
      var idPxl = charIDToTypeID( "#Pxl" );
      desc17.putUnitDouble( idblur, idPxl, 5.000000 );
      var idNose = charIDToTypeID( "Nose" );
      var idPrc = charIDToTypeID( "#Prc" );
      desc17.putUnitDouble( idNose, idPrc, 0.000000 );
      var idAntA = charIDToTypeID( "AntA" );
      desc17.putBoolean( idAntA, false );
      var idTrnS = charIDToTypeID( "TrnS" );
        var desc19 = new ActionDescriptor();
        var idNm = charIDToTypeID( "Nm " );
        desc19.putString( idNm, "Linear" );
      var idShpC = charIDToTypeID( "ShpC" );
      desc17.putObject( idTrnS, idShpC, desc19 );
      var idlayerConceals = stringIDToTypeID( "layerConceals" );
      desc17.putBoolean( idlayerConceals, true );
    var idDrSh = charIDToTypeID( "DrSh" );
    desc16.putObject( idDrSh, idDrSh, desc17 );
  var idLefx = charIDToTypeID( "Lefx" );
  desc15.putObject( idT, idLefx, desc16 );
executeAction( idsetd, desc15, DialogModes.NO );

Как вы думаете, что делает этот код? Он добавляет тень (Drop Shadow) к слою, это видно по название «DrSh». Я подозреваю, что внутри Photoshop-а прямо так и называются контролы в GUI.
Но, выполнив этот код, обнаружим, что он работает.
Можно найти, что executeAction может как показать диалог пользователю, так и сделать свою работу молча (это определяет последний параметр). Сами ID-шники нигде не описаны, о них (как и о том, что будет с ними в CS6) мы можем только гадать.
Тем не менее, фича логгирования действий довольно интересная, если очень надо, можно по-быстрому накидать скриптик для себя.

Ещё скрипты


Заодно я написал вот такие функции:

Если вам интересно, вы можете посмотреть их в том же скрипте наpastebin.

Интересные факты

Выводы


API вкусное, очень вкусное. Но отсутствие поддержки blending options сильно удручает; если они нужны – будьте готовы к тому, что придётся возиться со страшным кодом. Если всё, что вам надо (что как раз и надо в большинстве случаев от пакетной обработки) – обвести картинку рамочкой, думаю, ImageMagick в этом случае будет быстрее и намного удобнее.

+ / -


plus фильтры, гистограммы
plus RAW
plus color profiles, как в Photoshop-е
plus javascript – удобный, понятный почти всем язык
plus документация с примерами
minus отсутствие blending options
minus для работы нужен Photoshop /* внезапно */
minus работает довольно медленно


Источник: http://3d.arxua.com
Наш партнер:

Все самые свежие и актуальные отзывы о работодателях.

Похожие новости
  • Vibrance vs Saturation Lightroom
  • Lightroom на iPad
  • Мебельная фурнитура
  • Digital -Tutors Principles of Photoshop CS
  • Добро пожаловать!
  • Информация

    Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.