Script: PixelMath without open ImageWindow

outdoorboy

Well-known member
Hi,

How can I create a VIEW from an imagefile without opening an ImageWindow that I can edit with PixelMath?

JavaScript:
#include <pjsr/ColorSpace.jsh>
#include <pjsr/SampleType.jsh>
#include <pjsr/ResizeMode.jsh>

var folder;
var n = 0;
var dest;


function FileData( image, description, instance )
{
   this.image = image;
   this.description = description;
   this.filePath = instance.filePath;

   var windows;

   if ( instance.format.canStoreICCProfiles )
      this.iccProfile = instance.iccProfile;
   else
      this.iccProfile = undefined;

   if ( instance.format.canStoreKeywords )
      this.keywords = instance.keywords;
   else
      this.keywords = undefined;

   if ( instance.format.canStoreImageProperties && instance.format.supportsViewProperties )
   {
      this.properties = [];
      let properties = instance.imageProperties;
      for ( let i = 0; i < properties.length; ++i )
      {
         let value = instance.readImageProperty( properties[i][0]/*id*/ );
         if ( value != null )
            this.properties.push( { id:properties[i][0], type:properties[i][1], value:value } );
      }
   }
   else
      this.properties = undefined;

   if ( instance.format.canStoreThumbnails )
      this.thumbnail = instance.thumbnail;
   else
      this.thumbnail = undefined;

   this.openImages = () =>
   {
      windows = ImageWindow.open( this.filePath );
      for ( let i = 0; i < windows.length; ++i )
      {
         windows[i].show();
         windows[i].zoomToOptimalFit();
      }
   };

   this.closeImages = () =>
   {
      for ( let i = 0; i < windows.length; ++i )
      {
         windows[i].forceClose();
      }
   };
}

/*
 * Reads an image file.
 *
 * filePath    Path to the input file. The input format will be selected from
 *             the suffix (aka extension) of the file name in this path.
 *
 * inputHints  If defined, a string of input hints suitable for the format of
 *             the input file.
 *
 * floatSample If true, images will be read in a floating point format. If
 *             false, images will be read in unsigned integer format. If
 *             undefined, images will be read in the same format they are
 *             stored in the input file.
 *
 * bitsPerSample  If defined and valid, images will be read with the specified
 *             number of bits per pixel sample. If undefined or equal to zero,
 *             images will be read in the same format they are stored in the
 *             input file.
 *
 * Returns a new FileData object.
 */
function readImageFile( filePath, inputHints, floatSample, bitsPerSample )
{
   if ( inputHints === undefined )
      inputHints = "";

   let suffix = File.extractExtension( filePath ).toLowerCase();
   let format = new FileFormat( suffix, true/*toRead*/, false/*toWrite*/ );
   if ( format.isNull )
      throw new Error( "No installed file format can read \'" + suffix + "\' files." );

   let file = new FileFormatInstance( format );
   if ( file.isNull )
      throw new Error( "Unable to instantiate file format: " + format.name );

   let description = file.open( filePath, inputHints );
   if ( description.length < 1 )
      throw new Error( "Unable to open file: " + filePath );
   if ( description.length > 1 )
      console.warningln( "<end><cbr>** Ignoring additional images in file: " + filePath );

   if ( floatSample === undefined || floatSample <= 0 )
      floatSample = description[0].ieeefpSampleFormat;
   if ( bitsPerSample === undefined || bitsPerSample <= 0 )
      bitsPerSample = description[0].bitsPerSample;
   let image = new Image( 1, 1, 1, ColorSpace_Gray, bitsPerSample, floatSample ? SampleType_Real : SampleType_Integer );
   if ( !file.readImage( image ) )
      throw new Error( "Unable to read image: " + filePath );

   let data = new FileData( image, description[0], file );

   file.close();

   return data;
}

function intersect(source, dest)
{
   var P = new PixelMath;
   P.expression = "iif(" + source.currentView.id + ">0," + dest.currentView.id + "," + source.currentView.id + ")";
   P.expression1 = "";
   P.expression2 = "";
   P.expression3 = "";
   P.useSingleExpression = true;
   P.symbols = "";
   P.clearImageCacheAndExit = false;
   P.cacheGeneratedImages = false;
   P.generateOutput = true;
   P.singleThreaded = false;
   P.optimization = true;
   P.use64BitWorkingImage = false;
   P.rescale = false;
   P.rescaleLower = 0;
   P.rescaleUpper = 1;
   P.truncate = true;
   P.truncateLower = 0;
   P.truncateUpper = 1;
   P.createNewImage = false;
   P.showNewImage = true;
   P.newImageId = "";
   P.newImageWidth = 0;
   P.newImageHeight = 0;
   P.newImageAlpha = false;
   P.newImageColorSpace = PixelMath.prototype.SameAsTarget;
   P.newImageSampleFormat = PixelMath.prototype.SameAsTarget;

   P.executeOn(dest.currentView);
}

function myFunction(value)
{
   let data = readImageFile( value );

   data.openImages();    // >>>>>   this opens the ImageWindow   <<<<<

   // Get access to the current active image window.
   var source = ImageWindow.activeWindow;
   if ( source.isNull )
      throw new Error( "No active image" );
   else
   {
      intersect(source, dest);    // >>>>>    do PixelMath   <<<<<
   }

   data.closeImages();    // >>>>>    this close the ImageWindow   <<<<<
}

function main()
{
   Console.show();

   let files = getFiles();

   if (Parameters.isViewTarget)
   {
      Console.writeln("executing in view target context");
      Console.writeln("target: ", Parameters.targetView.id);
   }
   else if (Parameters.isGlobalTarget)
   {
      Console.writeln("executing in global context");
   }
   else
   {
      Console.writeln("executing in direct context");

      // Get access to the current active image window.
      dest = ImageWindow.activeWindow;
      if ( dest.isNull )
         throw new Error( "No image WHITE" );

      files.forEach(myFunction);
   }
}

main();

CS, Franz
 
I think a View will always have an associated ImageWindow but you can hide it from the user's view using the hide() method of ImageWindow.
 
If i use this function

JavaScript:
function myFunction1(value)
{
   let data = readImageFile( value );

   var windows = ImageWindow.open( data.filePath );
   for ( let i = 0; i < windows.length; ++i )
   {
      windows[i].show();
      windows[i].zoomToOptimalFit();
   }

   // Get access to the current active image window.
   var source = ImageWindow.activeWindow;
   if ( source.isNull )
      throw new Error( "No active image" );
   else
   {
      intersect(source, dest);
   }

   for ( let i = 0; i < windows.length; ++i )
   {
      windows[i].forceClose();
   }
}

this works fine.
If i remove both for loops

JavaScript:
function myFunction2(value)
{
   let data = readImageFile( value );

   var windows = ImageWindow.open( data.filePath );

   // Get access to the current active image window.
   var source = windows.mainView;
   if ( source.isNull )
      throw new Error( "No active image" );
   else
   {
      intersect(source, dest);
   }
}

i get
TypeError: source is undefined
After some trial and error, I arrived at this code.

JavaScript:
function intersect(source, dest)
{
   var P = new PixelMath;

   // old:      P.expression = "iif(" + source.currentView.id + ">0," + dest.currentView.id + "," + source.currentView.id + ")";
   P.expression = "iif(" + source.id + ">0," + dest.currentView.id + "," + source.id + ")";
   P.expression1 = "";
   P.expression2 = "";
   P.expression3 = "";
   P.useSingleExpression = true;
   P.symbols = "";
   P.clearImageCacheAndExit = false;
   P.cacheGeneratedImages = false;
   P.generateOutput = true;
   P.singleThreaded = false;
   P.optimization = true;
   P.use64BitWorkingImage = false;
   P.rescale = false;
   P.rescaleLower = 0;
   P.rescaleUpper = 1;
   P.truncate = true;
   P.truncateLower = 0;
   P.truncateUpper = 1;
   P.createNewImage = false;
   P.showNewImage = true;
   P.newImageId = "";
   P.newImageWidth = 0;
   P.newImageHeight = 0;
   P.newImageAlpha = false;
   P.newImageColorSpace = PixelMath.prototype.SameAsTarget;
   P.newImageSampleFormat = PixelMath.prototype.SameAsTarget;

   P.executeOn(dest.currentView);
}

function myFunction2(value)
{
   var source;
   let data = readImageFile( value );

   var windows = ImageWindow.open( data.filePath );

   // Get access to the current active image window.
   for ( let i = 0; i < windows.length; ++i )
   {
      // ??????????
      source = windows[i].currentView;
      Console.writeln("id: " + source.id);
   }

   if ( source.isNull )
      throw new Error( "No active image" );
   else
   {
      intersect(source, dest);
   }
}
This works but honestly I don't understand it myself.
Can anyone explain the background to me?

CS, Franz
 
The static method ImageWindow.open() returns an array of ImageWindows. In your second code snippet try:

JavaScript:
var source = windows[0].mainView;

This is effectively the same as your final code as the length of the windows array is 1, so your for loop runs just once with i = 0.
 
Last edited:
Back
Top