5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Photoshopで疑似網点生成するjsx

Posted at

Photoshopに疑似AM網点を生成させます。
アクションでできるのですが、網角と線数を都度設定したくて。

SS_Adobe Photoshop 2025_20250616-151130.png

90%GPTコードです。
https://d.pr/f/qXn80v

使い方

何でも良いんですが、
Illustratorデータを網点化してみましょう。

PhotoshopはIllustratorPDFの完璧なラスタライズはできません。Finder(QuickLook)やPreview.appと同程度の解釈しかできず、Acrobat(=印刷)と同じにはならないこともあります。

▼Photoshopで読み込むのはPDF部分なので、PDF互換ファイルを付けてください
SS_Finder_20250616-150028.png

aiファイルをPhotoshopに読ませると、ラスタライズ設定が出ます。
▼アンチエイリアスオフ、2,400ppiのCMYKでラスタライズさせてください。
SS_Finder_20250616-150055.png

▼開いたら、スクリプトを実行。プリセットにK45とM45、7度振りがあります。
SS_Finder_20250616-150122.png

網点化されます。
Photoshopの2階調ハーフトーンスクリーンはあくまでもPhotoshopの網点ですので、商業印刷で同じ形状にはなりませんし、モアレの確認などもってのほかですが、学習用としては使えます。

▼画像統合の上、チャンネル選択して全チャンネルの目玉を表示状態にしてから……
SS_Finder_20250616-150805.png

▼移動ツールでチャンネルごとにずらせば、版ズレのシミュレーションもできます。
名称未設定-1.png

以下コード

/*
<javascriptresource>
<name>疑似網点生成CMYK</name>
<category>YPresets</category>
</javascriptresource>
*/

(function () {

var keys = ["C", "M", "Y", "K"];
var presetNames = ["A: K45度_175線", "B: M45度_175線", "C: 7度_175線"];
var presets = [
  { C: [15, 175], M: [75, 175], Y: [0, 175], K: [45, 175] },
  { C: [15, 175], M: [45, 175], Y: [0, 175], K: [75, 175] },
  { C: [22, 175], M: [52, 175], Y: [7, 190], K: [82, 175] }
];

function buildDialog() {
  var dlg = new Window("dialog", "線数と角度の設定");
  dlg.orientation = "column";
  dlg.alignChildren = "left";

  var presetList = dlg.add("dropdownlist", undefined, presetNames);
  presetList.selection = 0;

  var inputGroup = dlg.add("group");
  inputGroup.orientation = "column";
  var inputFields = {};

  for (var i = 0; i < keys.length; i++) {
    var row = inputGroup.add("group");
    row.add("statictext", undefined, keys[i] + ": 角度");
    inputFields[keys[i]] = {};
    inputFields[keys[i]].angle = row.add("edittext", undefined, "0");
    inputFields[keys[i]].angle.characters = 5;
    row.add("statictext", undefined, "線数");
    inputFields[keys[i]].lpi = row.add("edittext", undefined, "0");
    inputFields[keys[i]].lpi.characters = 5;
  }

  var resGroup = dlg.add("group");
  resGroup.add("statictext", undefined, "出力解像度:");
  var resDropdown = resGroup.add("dropdownlist", undefined, ["4800", "2400", "1200", "600"]);
  resDropdown.selection = 1;
  inputFields.resolution = resDropdown;

  presetList.onChange = function () {
    var sel = presets[presetList.selection.index];
    for (var i = 0; i < keys.length; i++) {
      inputFields[keys[i]].angle.text = sel[keys[i]][0];
      inputFields[keys[i]].lpi.text = sel[keys[i]][1];
    }
  };
  presetList.notify();
  dlg.add("group").add("button", undefined, "OK");

  return dlg.show() == 1 ? inputFields : null;
}

function getScreenSettings(fields) {
  var s = {};
  for (var i = 0; i < keys.length; i++) {
    s[keys[i]] = {
      angle: parseFloat(fields[keys[i]].angle.text),
      lpi: parseFloat(fields[keys[i]].lpi.text)
    };
  }
  s.resolution = parseInt(fields.resolution.selection.text, 10);
  return s;
}

function binarizeChannel(doc, setting, resolution) {
  app.activeDocument = doc;
  // doc.resizeImage(undefined, undefined, resolution, ResampleMethod.NONE); // 解像度変更を無効化
  var bmo = new BitmapConversionOptions();
  bmo.resolution = resolution;
  bmo.method = BitmapConversionType.HALFTONESCREEN;
  bmo.frequency = setting.lpi;
  bmo.angle = setting.angle;
  bmo.shape = BitmapHalfToneType.ROUND;
  doc.changeMode(ChangeMode.BITMAP, bmo);
  doc.changeMode(ChangeMode.GRAYSCALE);
}

function mergeCMYKChannels(docNames) {
  var desc = new ActionDescriptor();
  var list = new ActionList();
  for (var i = 0; i < 4; i++) {
    var ref = new ActionReference();
    ref.putName(stringIDToTypeID("document"), docNames[i]);
    list.putReference(ref);
  }
  desc.putList(stringIDToTypeID("null"), list);
  desc.putEnumerated(stringIDToTypeID("mode"), stringIDToTypeID("colorSpace"), stringIDToTypeID("CMYKColorEnum"));
  try {
    executeAction(stringIDToTypeID("mergeChannels"), desc, DialogModes.NO);
  } catch (e) {
    alert("mergeChannels に失敗しました\n" + e);
  }
}

if (app.documents.length === 0 || app.activeDocument.mode !== DocumentMode.CMYK) {
  alert("CMYKモードの画像を開いてから実行してください。");
  return;
}

var inputFields = buildDialog();
if (!inputFields) return;

var screenSettings = getScreenSettings(inputFields);
var resolution = screenSettings.resolution;
var doc = app.activeDocument;
var dup = doc.duplicate(doc.name.replace(/\.[^\.]+$/, "") + "_複製", true);
try {
  dup.flatten();
} catch (e) {
  // 統合済みで flatten が不要な場合はスキップ
}
app.activeDocument = dup;
var splitDocs = dup.splitChannels();

var binarizedDocs = [];
for (var i = 0; i < keys.length; i++) {
  binarizeChannel(splitDocs[i], screenSettings[keys[i]], resolution);
  binarizedDocs.push(splitDocs[i]);
}

var docNames = [];
for (var i = 0; i < binarizedDocs.length; i++) {
  docNames.push(binarizedDocs[i].name);
}
mergeCMYKChannels(docNames);

})();
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?