0% found this document useful (0 votes)
12 views4 pages

FM Screening Simulation for Photoshop

The script simulates FM (Stochastic) screening in Photoshop by converting image channels to Bitmap mode using Diffusion Dither. It operates non-destructively on duplicates or split channels and prompts the user for the desired output resolution. The script supports Grayscale, RGB, and CMYK modes, handling errors during the conversion process and providing alerts for various outcomes.

Uploaded by

brandonc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views4 pages

FM Screening Simulation for Photoshop

The script simulates FM (Stochastic) screening in Photoshop by converting image channels to Bitmap mode using Diffusion Dither. It operates non-destructively on duplicates or split channels and prompts the user for the desired output resolution. The script supports Grayscale, RGB, and CMYK modes, handling errors during the conversion process and providing alerts for various outcomes.

Uploaded by

brandonc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

// SimulateFMScreening.

jsx
//
// This script simulates the effect of FM (Stochastic) screening
// by converting image channels to Bitmap mode using Diffusion Dither.
// It works non-destructively by operating on duplicates or split channels.

#target photoshop

// Main function wrapped in an anonymous function


(function() {

// Check if a document is open


if ([Link] === 0) {
alert("Error: No document open.\nPlease open an image file first.");
return; // Stop the script
}

// --- Configuration ---


// You could potentially preset a default resolution here,
// but prompting the user is generally better.
var defaultResolution = 300; // Example default DPI
// --- End Configuration ---

var doc = [Link];


var startRulerUnits = [Link];
[Link] = [Link]; // Use pixels for calculations

// Function to perform the Bitmap conversion


function convertToBitmapWithDiffusion(targetDoc, outputResolution) {
try {
// Ensure it's Grayscale first (necessary for Bitmap conversion)
if ([Link] != [Link]) {
[Link]([Link]);
}

// Conversion options
var bitmapOptions = new BitmapConversionOptions();
[Link] = [Link];
[Link] = outputResolution; // Use the provided
resolution

// Convert to Bitmap
[Link]([Link], bitmapOptions);
[Link] = [Link](/\.[^/.]+$/, "") +
" (FM Simulated)"; // Rename layer
return true; // Indicate success
} catch (e) {
alert("Error during Bitmap conversion on " + [Link] + ":\n" +
e);
// Attempt to close the potentially broken doc if it's a split channel
temp
if (targetDoc !== doc) { // Don't close original duplicate in case of
failure
try { [Link]([Link]); }
catch(closeError) {}
}
return false; // Indicate failure
}
}
// --- Main Logic ---

// Ask user for desired output resolution (controls dot density/fineness)


var userResolutionInput = prompt("Enter desired output resolution (in DPI) for
the FM simulation.\nHigher values create finer patterns.", defaultResolution);
if (userResolutionInput === null || userResolutionInput === "" ||
isNaN(parseFloat(userResolutionInput))) {
alert("Invalid resolution entered or process cancelled.");
[Link] = startRulerUnits; // Restore original ruler
units
return; // Stop script
}
var outputResolution = parseFloat(userResolutionInput);
if (outputResolution <= 0) {
alert("Resolution must be a positive number.");
[Link] = startRulerUnits; // Restore original ruler
units
return;
}

// Check the document's color mode


var docMode = [Link];

if (docMode == [Link]) {
alert("Image is already in Bitmap mode. Cannot apply FM simulation.");
[Link] = startRulerUnits;
return;
}

// --- Processing based on Color Mode ---

if (docMode == [Link]) {
alert("Processing Grayscale image.\nThe document will be duplicated and
converted.");
var dupDoc = [Link]("FM Simulated Grayscale", true); // Duplicate
the document
if (!convertToBitmapWithDiffusion(dupDoc, outputResolution)) {
alert("FM Simulation failed for Grayscale image.");
// dupDoc might have been closed by the error handler, or left open in
a failed state.
} else {
alert("Grayscale FM Simulation Complete.\nA new document has been
created.");
}

} else if (docMode == [Link] || docMode == [Link]) {

var colorSpaceName = (docMode == [Link]) ? "RGB" : "CMYK";


alert("Processing " + colorSpaceName + " image.\nChannels will be split
into separate Grayscale documents, then converted to Bitmap.");

// Duplicate the original document BEFORE splitting channels


// Splitting works on the active document and closes it.
var originalName = [Link];
var dupDocForSplitting = [Link](originalName + " (Temp for Split)",
true); // Make a safe copy to split
[Link] = dupDocForSplitting; // Ensure the duplicate is active
try {
// Store current channel names (important!)
var channelNames = [];
for (var i = 0; i < [Link]; i++) {
// Only store actual color channels, ignore masks etc.
if ( (docMode == [Link] &&
[Link][i].kind === [Link]) ||
(docMode == [Link] &&
[Link][i].kind === [Link]) ) {
[Link]([Link][i].name);
}
}

// Flatten the duplicate before splitting to avoid layer issues


[Link]();

// Split Channels - This closes dupDocForSplitting and creates new


grayscale docs
[Link](stringIDToTypeID("splitChannels")); // Use TypeID for
reliability

// Now, loop through the NEWLY opened documents (which are the
channels)
// We need to figure out which documents were just created. This is
tricky.
// A common way is to assume they are the most recently opened
documents.
var numChannels = [Link];
var openedDocs = [Link];
var processedCount = 0;

// Iterate backwards through documents as splitting opens them in a


certain order
for (var i = [Link] - 1; i >= 0 && processedCount <
numChannels; i--) {
var channelDoc = openedDocs[i];
// Check if the doc name seems to match one of the split channels
// (Photoshop usually names them like 'OriginalName_ChannelName')
var isLikelyChannel = false;
for(var j=0; j<[Link]; j++) {
// Check if doc name ends with _ChannelName (more robust check)
var expectedSuffix = "_" + channelNames[j];
if ([Link] > [Link] &&
[Link]([Link] -
[Link]) === expectedSuffix) {
isLikelyChannel = true;
break;
}
}

// Alternative check: If the document mode is Grayscale and wasn't


the original doc
if (!isLikelyChannel && [Link] === [Link]
&& [Link] !== [Link]) {
// This might be a fallback, less reliable if other grayscale
docs are open
// isLikelyChannel = true; // Uncomment cautiously if name
check fails
}

if (isLikelyChannel) {
[Link] = channelDoc; // Activate the channel
document
if (convertToBitmapWithDiffusion(channelDoc, outputResolution))
{
processedCount++;
} else {
alert("FM Simulation failed for channel: " +
[Link] + ".\nThis channel document might be closed or left in an error
state.");
// Don't increment processedCount on failure
}
}
}

if (processedCount === numChannels) {


alert(colorSpaceName + " FM Simulation Complete.\nEach channel (" +
[Link](", ") + ") has been processed into a separate Bitmap document.");
} else {
alert("Warning: Processed " + processedCount + " out of " +
numChannels + " channels. Please check the open documents. Some channel conversions
might have failed.");
}

} catch (e) {
alert("An error occurred during the channel splitting or processing:\n"
+ e);
// Attempt to close the temporary duplicate if it still exists
(unlikely after split)
try { [Link]([Link]); }
catch(closeError) {}
}

} else {
alert("Unsupported document mode: " + docMode + "\nThis script only
supports Grayscale, RGB, and CMYK modes.");
}

// Restore original ruler units


[Link] = startRulerUnits;

})(); // End of anonymous function wrapper

You might also like