// (c) Copyright 2005.  Adobe Systems, Incorporated.  All rights reserved.



//

// Lens Correct automation in JavaScript

//

// 

// Copy the .jsx file to Adobe Photoshop CS5/Presets/Scripts and

// .eve file to Adobe Photoshop CS5/Presets/Scripts/Stack Scripts Only/

//



/*

@@@BUILDINFO@@@ Lens Correct.jsx

*/



/*

// BEGIN__HARVEST_EXCEPTION_ZSTRING



<javascriptresource>

<name>$$$/JavaScripts/LensCorrect/Menu=Lens Correction...</name>

<menu>automate</menu>

</javascriptresource>



// END__HARVEST_EXCEPTION_ZSTRING

*/





// on localized builds we pull the $$$/Strings from a .dat file

$.localize = true;



// Put header files in a "Stack Scripts Only" folder.  The "...Only" tells

// PS not to place it in the menu.  For that reason, we do -not- localize that

// portion of the folder name.

var g_StackScriptFolderPath = app.path + "/"+ localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts") + "/"

										+ localize("$$$/Private/Exposuremerge/StackScriptOnly=Stack Scripts Only/");



$.evalFile(g_StackScriptFolderPath + "LatteUI.jsx");

$.evalFile(g_StackScriptFolderPath + "StackSupport.jsx");

$.evalFile(g_StackScriptFolderPath + "CreateImageStack.jsx");



// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)

// Must leave at zero, otherwise trapping gFileFromBridge fails on QA's debug builds.

$.level = 2; // (Window.version.search("d") != -1) ? 1 : 0;

// debugger; // launch debugger on next line



var outFolder;

var lcpFile;

var saveType;

var edgeType;

var correctGD;

var correctCA;

var correctVignette;

var autoScaleImage;



var jpegTypeItem = "JPG";

var psdTypeItem = "PSD";



var edgeExtension = localize("$$$/LensCorrect/Dialog/FillType/Popup/EdgeExtension=Edge Extension");

var edgeTransparency = localize("$$$/LensCorrect/Dialog/FillType/Popup/Transparency=Transparency");

var edgeBlackColor = localize("$$$/LensCorrect/Dialog/FillType/Popup/BlackColor=Black Color");

var edgeWhiteColor = localize("$$$/LensCorrect/Dialog/FillType/Popup/WhiteColor=White Color");

    

// Keeps the settings of the script dialog

function LensCorrect( )

{

    //This is an example descriptor code

    //IT IS NOT USED IN THIS EXAMPLE, HERE FOR DOCUMENTATION PURPOSES

    //If it's not defined/passed in, plugin will use default values

    this.lcpDesc = new ActionDescriptor();

    //Auto Correct Geometric Distortion

	var idLnAg = charIDToTypeID( "LnAg" );

    this.lcpDesc.putBoolean( idLnAg, true );

    //Auto Correct Chromatic Aberration

    var idLnAc = charIDToTypeID( "LnAc" );

    this.lcpDesc.putBoolean( idLnAc, true );

    //Auto Vignette Removal

    var idLnAv = charIDToTypeID( "LnAv" );

    this.lcpDesc.putBoolean( idLnAv, true );

    //Auto Scale Image

    var idLnAs = charIDToTypeID( "LnAs" );

    this.lcpDesc.putBoolean( idLnAs, true );

    //Auto Profile Interpolation

    var idLnIp = charIDToTypeID( "LnIp" );

    this.lcpDesc.putBoolean( idLnIp, false );

    //Focus Distance

    var idLnFo = charIDToTypeID( "LnFo" );

    this.lcpDesc.putDouble( idLnFo, 0.000000 );

    //LCP Path (this descriptor is used in this code, so below is another example)

    var idLnPp = charIDToTypeID( "LnPp" );

    this.lcpDesc.putString( idLnPp, "" );

    //Applied Lens Profile

    var idLnPr = charIDToTypeID( "LnPr" );

    this.lcpDesc.putString( idLnPr, "" );					// setup null profile

    //CUSTOM SETTINGS

    //Distortion Amount

    var idLnIa = charIDToTypeID( "LnIa" );

    this.lcpDesc.putDouble( idLnIa, 0.000000 );

    //Distortion Coefficient 0

    var idLnIzero = charIDToTypeID( "LnI0" );

    this.lcpDesc.putDouble( idLnIzero, 0.000000 );

    //Distortion Coefficient 1

    var idLnIone = charIDToTypeID( "LnI1" );

    this.lcpDesc.putDouble( idLnIone, 0.000000 );

    //Distortion Coefficient 2

    var idLnItwo = charIDToTypeID( "LnI2" );

    this.lcpDesc.putDouble( idLnItwo, 0.000000 );

    //Distortion Coefficient 3

    var idLnIthree = charIDToTypeID( "LnI3" );

    this.lcpDesc.putDouble( idLnIthree, 1.000000 );

    //Rotation Angle

    var idLnRa = charIDToTypeID( "LnRa" );

    this.lcpDesc.putDouble( idLnRa, 0.000000 );

    //Vertical Perspective

    var idLnVp = charIDToTypeID( "LnVp" );

    this.lcpDesc.putDouble( idLnVp, 0.000000 );

    //HOrizontal Perspective

    var idLnHp = charIDToTypeID( "LnHp" );

    this.lcpDesc.putDouble( idLnHp, 0.000000 );

    //Correction Size

    var idLnSi = charIDToTypeID( "LnSi" );

    this.lcpDesc.putDouble( idLnSi, 100.000000 );

    //Edge Fill Type

    var idLnFt = charIDToTypeID( "LnFt" );

    this.lcpDesc.putInteger( idLnFt, 2 );

    //Vignette Amount

    var idLnSb = charIDToTypeID( "LnSb" );

    this.lcpDesc.putDouble( idLnSb, 0.000000 );

    //Vignette Midpoint

    var idLnSt = charIDToTypeID( "LnSt" );

    this.lcpDesc.putInteger( idLnSt, 50 );

    //Aberration Red/Cyan

    var idLnRc = charIDToTypeID( "LnRc" );

    this.lcpDesc.putDouble( idLnRc, 0.000000 );

    //Aberration Green/Magenta

    var idLnGm = charIDToTypeID( "LnGm" );

    this.lcpDesc.putDouble( idLnGm, 0.000000 );

    //Aberration Blue/Yellow

    var idLnBy = charIDToTypeID( "LnBy" );

    this.lcpDesc.putDouble( idLnBy, 0.000000 );

    //Grid Size

    var idLnNa = charIDToTypeID( "LnNa" );

    this.lcpDesc.putInteger( idLnNa, 64 );

    //Grid Horizontal Offset

    var idLnIh = charIDToTypeID( "LnIh" );

    this.lcpDesc.putInteger( idLnIh, 0 );

    //Grid Vertical Offset

    var idLnIv = charIDToTypeID( "LnIv" );

    this.lcpDesc.putInteger( idLnIv, 0 );

    //Grid Color

    var idLnIs = charIDToTypeID( "LnIs" );

        var desc4 = new ActionDescriptor();

        var idRd = charIDToTypeID( "Rd  " );

        desc4.putDouble( idRd, 127.000000 );

        var idGrn = charIDToTypeID( "Grn " );

        desc4.putDouble( idGrn, 127.000000 );

        var idBl = charIDToTypeID( "Bl  " );

        desc4.putDouble( idBl, 127.000000 );

    var idRGBC = charIDToTypeID( "RGBC" );

    this.lcpDesc.putObject( idLnIs, idRGBC, desc4 );

    //Show Grid

    var idLnNm = charIDToTypeID( "LnNm" );

    this.lcpDesc.putBoolean( idLnNm, false );

		

    		

}



LensCorrect.prototype.runOnInput = function(files)

{

    var idLnCr = charIDToTypeID( "LnCr" );

    var args = new ActionDescriptor();

    var idLnPp = charIDToTypeID( "LnPp" );

    if (!this.autoMatch && lcpFile != null && lcpFile.exists)

		args.putString( idLnPp, lcpFile.fsName );	// setup the full lcp file path

	else

		args.putString( idLnPp, "" );

		

	 //Auto Correct Geometric Distortion

	var idLnAg = charIDToTypeID( "LnAg" );

    args.putBoolean( idLnAg, Boolean(correctGD) );

    //Auto Correct Chromatic Aberration

    var idLnAc = charIDToTypeID( "LnAc" );

    args.putBoolean( idLnAc, Boolean(correctCA));

    //Auto Vignette Removal

    var idLnAv = charIDToTypeID( "LnAv" );

    args.putBoolean( idLnAv, Boolean(correctVignette));

    //Auto Scale Image

    var idLnAs = charIDToTypeID( "LnAs" );

    args.putBoolean( idLnAs, Boolean(autoScaleImage));

    

   	

    var idLnFt = charIDToTypeID( "LnFt" );

    switch (edgeType)

    {

        case edgeExtension:

        {

            args.putInteger( idLnFt, 1);

            break;

        }

        case edgeTransparency:

        {

            args.putInteger( idLnFt, 2);

            break;

        }

        case edgeBlackColor:

        {

            args.putInteger( idLnFt, 3);

            break;

        }

        case edgeWhiteColor:

        {

            args.putInteger( idLnFt, 4);

            break;

        }

        default:

        {

            args.putInteger( idLnFt, 1);

            break;

        }

    }



    var i;

    try {

        for (i in files)

        {

            open (files[i].file);

            app.activeDocument.flatten();

            var result = executeAction( idLnCr, args, DialogModes.NO );

            app.refresh();

            

            var options;

            switch (saveType)

            {

                case jpegTypeItem:

                {

                    options = new JPEGSaveOptions;

                    options.quality = 8;

                    break;

                }

                case psdTypeItem:

                {

                    options = new PhotoshopSaveOptions;

                    break;

                }

            }



            var outfile = new File(outFolder.fsName.toString() + "/" + files[i].file.name);

            if (!outFolder.exists)

                outFolder.create();

                

		   app.activeDocument.saveAs (outfile, options, true);

           

            // close the document

            app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

       }

        return result;

    }

    catch(err)

    {

        if (err.number != kUserCanceledError)

            alert(err, this.pluginName, true);

            

         // close the document

        app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);    

        return null;

    }

    return -1;

}



LensCorrect.prototype.showDialog = function( )

{

    var autoMatchLcp = true;

    var outputSelected = false;

	var lcpSelected = false;

   var inputFiles = new Array();

    var w = latteUI( g_StackScriptFolderPath + 'LensCorrect.exv' );

    var fileMenuItem =            localize("$$$/Project/Exposuremerge/Files/Files=Files");

    var folderMenuItem =        localize("$$$/Project/Exposuremerge/Files/Folder=Folder");

    var openFilesMenuItem =   localize("$$$/Project/Exposuremerge/Files/Open=Open Files");



    

    function enableControls()

    {

        w.findControl('_browse').enabled = true;

        w.findControl('_remove').enabled = (inputFiles.length > 0) && w.findControl('_fileList').selection;

        w.findControl('_ok').enabled = (inputFiles.length > 0) && outputSelected && (lcpSelected || autoMatchLcp);

        w.findControl('_chooselcp').enabled = !w.findControl('_automatch').value;

    }



    function addFileToList(f)

	{

		var i;

		if (f == null)

			return;

			

		for (i in inputFiles)

			if (f.toString() == inputFiles[i].file.toString())	// Already in list?

				return;

				

		// Windows - use filter to skip evil sidecar files

		if ((File.fs == "Windows") && !winFileSelection( f ))

			return;



		var fileList = w.findControl('_fileList');

		fileList.add('item', File.decode(f.name) );

		inputFiles.push(new StackElement(f));

	}



    function updateDestination()

    {

            if (outputSelected)

                return;

            if (inputFiles[0] != null) 

            {

                outFolder = Folder(File(inputFiles[0].file.toString()).parent.fsName + '/results');

                w.findControl('_destination').text = outFolder.fsName;

                outputSelected = true;

            }

    }



	

    // Dialog event handling routines

	

	function removeOnClick()

	{

		var i, s;

		var selList = w.findControl('_fileList').selection;

		for (s in selList)

		{

			for (i in inputFiles)

				if (File.decode(inputFiles[i].file.name) == selList[s].text)

				{

					inputFiles.splice(i,1);

					break;

				}

			w.findControl('_fileList').remove(selList[s]);

		}

		enableControls();

	}

	

	function browseOnClick()

	{

		// Spring back to the "File..." menu item

		var menu = w.findControl('_source');

//		menu.items[0].selected = true;

		switch (menu.selection.text)

		{

			case fileMenuItem:

			{

				var i, filenames = photoshopFileOpenDialog();

				if (filenames.length)

				{

					if (File.fs == "Macintosh")	// Mac gratiuitously scrambles them...why?

						filenames.sort();

					for (i in filenames)

						addFileToList( File(filenames[i]) );

				}

				break;

			}

			case folderMenuItem:

			{

				var folder = Folder.selectDialog(localize('$$$/AdobePlugin/Exposuremerge/FolderSelect=Select folder'));

				if (folder)

				{

					fileList = folder.getFiles( $.os.match(/^Macintosh.*/) ? macFileSelection : winFileSelection );

					var f;

					for (f in fileList)

						addFileToList(fileList[f]);

				}

				break;

			}

		}

        updateDestination();

		enableControls();

		return;

	}

	

	function addOpenDocuments()

	{

		var gaveUnsavedWarning = false;



		// doc.saved is true when a new empty document is created.

		function isReallySaved( doc )

		{

			if (! doc.saved)

				return false;

			try

			{

				var n = doc.fullName;

			}

			catch (err)	// Mainly for err.number == 8103, error.message == "The document has not yet been saved"

			{				// But if anything else goes wrong, we still don't want it.

				return false;

			}

			return true;

		}

		

		var i, haveUnsavedDocuments = false;

		for (i = 0; i < app.documents.length; i++)

			if (isReallySaved(app.documents[i]))

				addFileToList( File( app.documents[i].fullName ) );

			else

				haveUnsavedDocuments = true;

				

		if (haveUnsavedDocuments && !gaveUnsavedWarning)

		{

			alert(localize('$$$/AdobePlugin/LensCorrect/Mustsave=Documents must be saved before they can be corrected'));

			gaveUnsavedWarning = true;

			w.findControl('_source').items[0].selected = true;

		}

        updateDestination();

		enableControls();

	}

	

	function sourceMenuOnChange()

	{

		var menu = w.findControl('_source');

		localUseLayeredDocument = false;

		

		switch (menu.selection.text) 

		{

			case fileMenuItem:		break;		// default

			case folderMenuItem:		break;

			case openFilesMenuItem:

				addOpenDocuments();

				break;

			case openLayeredDocMenuItem:

				w.findControl('_fileList').removeAll();

				inputFiles = [];

				localUseLayeredDocument = true;

		}

		enableControls();

	}



    function typesOnChange()

    {

            var menu = w.findControl('_filetypes');

            

            saveType = menu.selection.text;

    }



    function edgeOnChange()

    {

            var menu = w.findControl('_edgetypes');

            edgeType = menu.selection.text;

     }



	function listOnChange()

	{

		enableControls();

	}



    function autoMatchOnChange()

    {

		autoMatchLcp = w.findControl('_automatch').value;

		lcpSelected = (!w.findControl('_automatch').value && lcpFile != null && lcpFile.exists);

		

        enableControls();

    }



    function chooseLcpOnClick()

    {

        var promptLCP = localize("$$$/AdobePlugin/LensCorrect/ChooseLCP=Please select the lens profile (LCP) to apply.");

        lcpFile = File.openDialog(promptLCP, "*.lcp", false);

	    lcpSelected = (lcpFile != null && lcpFile.exists);

		if (lcpSelected) {

			w.findControl('_lcpFile').text = lcpFile.displayName;

		}

	enableControls();

    }



    function chooseDestOnClick()

    {

        var promptOutput = localize("$$$/AdobePlugin/LensCorrect/ChooseDest=Please specify destination file folder:");

        outFolder = Folder.selectDialog(promptOutput);

        outputSelected = (outFolder != null && outFolder.exists);

        if (outputSelected) {

            w.findControl('_destination').text = outFolder.fsName;

        }

        enableControls();

    }



    w.text = localize("$$$/AdobePlugin/Shared/LensCorrect/Process/Name=Lens Correction")

    w.center();

    if (this.introText)

        w.findControl('_intro').text = this.introText;

    //Set up source menu

    var menu = w.findControl('_source');

    menu.add( 'item', fileMenuItem );

    menu.add( 'item', folderMenuItem );

    // The "addOpenDocs" button was added at the last moment.  If it's

	// there, then use that in favor of the menu.

	var addOpenDocsButton = w.findControl('_addOpenDocs');

	// Really, you want to disable the menu, but that's not possible w/ScriptUI

	if (app.documents.length > 0 && !addOpenDocsButton)

		menu.add( 'item', openFilesMenuItem ); 

    menu.items[0].selected = true;

	menu.preferredSize.width = 214;	// Brute force fix for PR1355780

    

    w.findControl('_automatch').value = true;

	w.findControl('_correctGD').value = true;

	w.findControl('_correctCA').value = true;

	w.findControl('_vignette').value = true;

    w.findControl('_autoScale').value = true;

    

    //Save Types

    var filetypemenu = w.findControl('_filetypes');

    filetypemenu.add('item', jpegTypeItem);

    filetypemenu.add('item', psdTypeItem);

    

    filetypemenu.items[1].selected = true;

    

    var edgetypemenu = w.findControl('_edgetypes');

    edgetypemenu.add('item', edgeExtension);

    edgetypemenu.add('item', edgeTransparency);

    edgetypemenu.add('item', edgeBlackColor);

    edgetypemenu.add('item', edgeWhiteColor);

    

    edgetypemenu.items[1].selected = true;    

	

    var fileSelection;

    

    w.findControl('_browse').onClick = browseOnClick;

	w.findControl('_fileList').onChange = listOnChange;

	w.findControl('_remove').onClick = removeOnClick;

	w.findControl('_source').onChange = sourceMenuOnChange;

    w.findControl('_automatch').onClick = autoMatchOnChange;

    w.findControl('_chooselcp').onClick = chooseLcpOnClick;

    w.findControl('_choosedest').onClick = chooseDestOnClick;

    w.findControl('_filetypes').onChange = typesOnChange;

    w.findControl('_edgetypes').onChange = edgeOnChange;

    

    if (addOpenDocsButton)

	{

		addOpenDocsButton.onClick = addOpenDocuments;

		addOpenDocsButton.enabled = app.documents.length > 0;

	}

	else		

		addOpenDocuments();

        

    // If we already have stackElements (e.g., from Bridge) add them

	if (this.stackElements)

	{

		for (i in this.stackElements)

			addFileToList( this.stackElements[i].file );

	}



	enableControls();

    

    var result = w.show();

    if (result != kCanceled)

    {

        correctGD = w.findControl('_correctGD').value;

        correctCA = w.findControl('_correctCA').value;

        correctVignette = w.findControl('_vignette').value;

        autoScaleImage = w.findControl('_autoScale').value;

        return inputFiles;

    } else {

        if (File.fs == "Macintosh")

            app.bringToFront();

        return null;

    }

}



lensCorrect = new LensCorrect ();

var files = lensCorrect.showDialog();

if (files)

    lensCorrect.runOnInput(files);





