// (c) Copyright 2007 Adobe Systems, Inc. All rights reserved. // Written by Ed Rose // based on the ADM Mode Change by Joe Ault from 1998 /* @@@BUILDINFO@@@ Conditional Mode Change.jsx 1.0.0.14 */ /* Special properties for a JavaScript to enable it to behave like an automation plug-in, the variable name must be exactly as the following example and the variables must be defined in the top 10000 characters of the file // BEGIN__HARVEST_EXCEPTION_ZSTRING $$$/JavaScripts/ModeChange/Name=Conditional Mode Change... automate true 8cba8cd6-cb66-11d1-bc43-0060b0a13dc4 >] >> /Enums << /sourceModeType << /uIBitmap ($$$/AdobePlugin/ConditionalModeChange/Bitmap=Bitmap) /uIGrayscale ($$$/AdobePlugin/ConditionalModeChange/Grayscale=Grayscale) /uIDuotone ($$$/AdobePlugin/ConditionalModeChange/Duotone=Duotone) /uIIndexed ($$$/AdobePlugin/ConditionalModeChange/Indexed=Indexed) /uIRGB ($$$/AdobePlugin/ConditionalModeChange/RGB=RGB) /uICMYK ($$$/AdobePlugin/ConditionalModeChange/CMYK=CMYK) /uILab ($$$/AdobePlugin/ConditionalModeChange/Lab=Lab) /uIMultichannel ($$$/AdobePlugin/ConditionalModeChange/Multichannel=Multichannel) >> >> >> ]]> // END__HARVEST_EXCEPTION_ZSTRING */ // enable double clicking from the Macintosh Finder or the Windows Explorer #target photoshop // debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning) //$.level = 1; //debugger; // launch debugger on next line // on localized builds we pull the $$$/Strings from a .dat file, see documentation for more details $.localize = true; var gScriptResult; // ok and cancel button var okButtonID = 1; var cancelButtonID = 2; // the main routine // the ModeChange object does most of the work try { GlobalVariables(); CheckVersion(); // create our default params var changeInfo = new ChangeInfo(); var gMC = new ModeChange(); if ( DialogModes.ALL == app.playbackDisplayDialogs ) { gMC.CreateDialog(); if (cancelButtonID == gMC.RunDialog() ) { // <- this calls MCExecute gScriptResult = 'cancel'; } } else { if ( gMC.InitVariables() ) { // only proceed if document to change if ( ! MCExecute() ) { gScriptResult = 'cancel'; } } else { gScriptResult = 'cancel'; } } if (!rollItBack) { // rollItBack is set false when MCExecute correctly happens SaveOffParameters(changeInfo); } } // Lot's of things can go wrong // Give a generic alert and see if they want the details catch( e ) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert( e + " : " + e.line ); } gScriptResult = 'cancel'; } // restore the dialog modes app.displayDialogs = gSaveDialogMode; gScriptResult; ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // created via new ChangeInfo(), above function SaveOffParameters(changeInfo) { // save off our last run parameters var d = ChangeInfoToDescriptor(changeInfo, strMessage); app.putCustomOptions("85d5fff3-b16f-432c-96e6-6dbbedbbdcda", d); app.playbackDisplayDialogs = DialogModes.ALL; var dd = ChangeInfoToDescriptor(changeInfo, strMessage); app.playbackParameters = dd; } function GlobalVariables() { // a version for possible expansion issues gVersion = 1; // remember the dialog modes gSaveDialogMode = app.displayDialogs; app.displayDialogs = DialogModes.NO; // // all the strings that need to be localized // // title of app strTitle = localize( "$$$/JavaScript/ModeChange/Title=Conditional Mode Change" ); // buttons strButtonOK = localize("$$$/JavaScripts/ModeChange/OK=OK"); strButtonCancel = localize("$$$/JavaScripts/ModeChange/Cancel=Cancel"); strButtonAll = localize("$$$/JavaScripts/ModeChange/All=&All"); strButtonNone = localize("$$$/JavaScripts/ModeChange/None=&None"); // panel strings strSrcMode = localize("$$$/JavaScripts/ModeChange/SrcMode=Source Mode"); strTargMode = localize("$$$/JavaScripts/ModeChange/TargetMode=Target Mode"); // checkbox strings strChkBitmap = localize("$$$/JavaScripts/ModeChange/ChkBitmap=&Bitmap"); strChkGraysc = localize("$$$/JavaScripts/ModeChange/ChkGraysc=&Grayscale"); strChkDuotone = localize("$$$/JavaScripts/ModeChange/ChkDuotone=&Duotone"); strChkIxClr = localize("$$$/JavaScripts/ModeChange/ChkIxClr=&Indexed Color"); strChkRGB = localize("$$$/JavaScripts/ModeChange/ChkRGB=&RGB Color"); strChkCMYK = localize("$$$/JavaScripts/ModeChange/ChkCMYK=&CMYK Color"); strChkLab = localize("$$$/JavaScripts/ModeChange/ChkLab=&Lab Color"); strChkMChan = localize("$$$/JavaScripts/ModeChange/ChkMChan=M&ultichannel"); // popup strings strPopBitmap = localize("$$$/JavaScripts/ModeChange/PopBitmap=Bitmap"); strPopGraysc = localize("$$$/JavaScripts/ModeChange/PopGraysc=Grayscale"); strPopDuotone = localize("$$$/JavaScripts/ModeChange/PopDuotone=Duotone"); strPopIxClr = localize("$$$/JavaScripts/ModeChange/PopIxClr=Indexed Color"); strPopRGB = localize("$$$/JavaScripts/ModeChange/PopRGB=RGB Color"); strPopCMYK = localize("$$$/JavaScripts/ModeChange/PopCMYK=CMYK Color"); strPopLab = localize("$$$/JavaScripts/ModeChange/PopLab=Lab Color"); strPopMChan = localize("$$$/JavaScripts/ModeChange/PopMChan=Multichannel"); // label strModeLbl = localize("$$$/JavaScripts/ModeChange/ModeLbl=&Mode:"); // alert dialog strings strTextNeedFile = localize("$$$/JavaScripts/ModeChange/NeedFile=You must have a file selected before using Conditional Mode Change"); strTextModeMatch = localize("$$$/JavaScripts/ModeChange/ModeMatch=Mode of the document does not match any selected Source Modes."); strTextOneSrcMode = localize("$$$/JavaScripts/ModeChange/OneSrcMode=At least one Source Mode must be selected."); strTextErrRetHist = localize("$$$/JavaScripts/ModeChange/ErrRetHist=Error retrieving history preferences."); strTextErrSetHist = localize("$$$/JavaScripts/ModeChange/ErrSetHist=Error setting history preferences."); strTextErrDocAttr = localize("$$$/JavaScripts/ModeChange/ErrDocAttr=Error retrieving document attributes. No conversion performed."); strTextErrIntCnv8 = localize("$$$/JavaScripts/ModeChange/ErrIntCnv8=Error with intermediate conversion to 8-bit color."); strTextErrCvtRGB = localize("$$$/JavaScripts/ModeChange/ErrCvtRGB=Error with conversion to RGB color mode."); strTextErrCvtGray = localize("$$$/JavaScripts/ModeChange/ErrCvtGray=Error with conversion to Grayscale mode."); strTextErrCvtTarg = localize("$$$/JavaScripts/ModeChange/ErrCvtTarg=Error with converting to Target Mode."); strTextModeSame = localize("$$$/JavaScripts/ModeChange/ModeSame=Mode of the document is the same as the Target Mode. No conversion performed."); strTextErrIntCnv16 = localize("$$$/JavaScripts/ModeChange/ErrIntCnv16=Error with intermediate conversion to 16-bit color."); strMessage = localize("$$$/JavaScripts/ModeChange/Message=Conditional Mode Change action settings"); strMustUse = localize( "$$$/JavaScripts/ImageProcessor/MustUse=You must use Photoshop CS 2 or later to run this script!" ); // bit flags for checkboxes FLAG_BITMAP = false; FLAG_GRAYSCALE = false; FLAG_DUOTONE = false; FLAG_INDEXED = false; FLAG_RGB = true; FLAG_CMYK = false; FLAG_LAB = false; FLAG_MULTICHANNEL = false; // constants FLATTEN_UNUSED = 99; // flattening unspecified DEPTH_UNSET = 99; // depth of the document unset classNull = charIDToTypeID( 'null' ); // ain't nothing here (error) classBitmapMode = charIDToTypeID( 'BtmM' ); classGrayscaleMode = charIDToTypeID( 'Grys' ); classDuotoneMode = charIDToTypeID( 'DtnM' ); classIndexedColorMode = charIDToTypeID( 'IndC' ); classRGBColorMode = charIDToTypeID( 'RGBM' ); classCMYKColorMode = charIDToTypeID( 'CMYM' ); classLabColorMode = charIDToTypeID( 'LbCM' ); classMultichannelMode = charIDToTypeID( 'MltC' ); enumUIMultichannel = charIDToTypeID( 'UMlt' ); enumUILab = charIDToTypeID( 'ULab' ); enumUICMYK = charIDToTypeID( 'UCMY' ); enumUIRGB = charIDToTypeID( 'URGB' ); enumUIIndexed = charIDToTypeID( 'UInd' ); enumUIDuotone = charIDToTypeID( 'UDtn' ); enumUIGrayscale = charIDToTypeID( 'UGry' ); enumUIBitmap = charIDToTypeID( 'UBtm' ); keySourceMode = charIDToTypeID( 'SrcM' ); typeSourceMode = charIDToTypeID( 'Cndn' ); keyDestinationMode = charIDToTypeID( 'DstM' ); keyMerge = charIDToTypeID( 'Mrge' ); keyMessage = charIDToTypeID( 'Msge' ); // variables rollItBack = true; // flag to tell whether to roll back (assumed true until valid MCExecute) } // the main class function ModeChange() { this.CreateDialog = function() { var res = "dialog { \ ModesOKCancel: Group { orientation: 'row', \ STModes: Group { orientation: 'column', \ src: Panel { orientation: 'row', \ text: '" + strSrcMode +"', \ L1: Group { orientation: 'column', \ bmp: Checkbox { text:'" + strChkBitmap +"', alignment:'left'}, \ gry: Checkbox { text:'" + strChkGraysc + "', alignment:'left'}, \ duo: Checkbox { text:'" + strChkDuotone + "', alignment:'left'}, \ ixc: Checkbox { text:'" + strChkIxClr + "', alignment:'left'}, \ AORN: Group { orientation: 'row', \ all: Button { text:'" + strButtonAll +"', properties:{name:'all'} }, \ non: Button { text:'" + strButtonNone +"', properties:{name:'none'} } \ } \ }, \ L2: Group { orientation: 'column', alignment: 'top', \ rgb: Checkbox { text:'" + strChkRGB + "', alignment:'left'}, \ cmy: Checkbox { text:'" + strChkCMYK + "', alignment:'left'}, \ lab: Checkbox { text:'" + strChkLab + "', alignment:'left'}, \ mch: Checkbox { text:'" + strChkMChan + "', alignment:'left'} \ } \ }, \ targ: Panel { orientation: 'column', \ text: '" + strTargMode +"', \ w: Group { orientation: 'row', \ mod: StaticText { text:'" + strModeLbl +"' }, \ drp: DropDownList {alignment:'left'} \ }, \ }, \ }, \ buttons: Group { alignChildren: 'fill', orientation: 'column', alignment: 'top', \ okBtn: Button { text:'" + strButtonOK +"', properties:{name:'ok'} }, \ cancelBtn: Button { text:'" + strButtonCancel + "', properties:{name:'cancel'} } \ } \ } \ }"; // create the main dialog window, this holds all our data this.dlgMain = new Window(res,strTitle); // create a shortcut for easier typing var d = this.dlgMain; var drop = d.ModesOKCancel.STModes.targ.w.drp; // for easier typing drop.add('item',strPopBitmap); // 0 drop.add('item',strPopGraysc); // 1 drop.add('item',strPopDuotone); // 2 drop.add('item',strPopIxClr); // 3 drop.add('item',strPopRGB); // 4 drop.add('item',strPopCMYK); // 5 drop.add('item',strPopLab); // 6 drop.add('item',strPopMChan); // 7 drop.selection = drop.items[5]; // CMYK changeInfo.destinationMode = 5; changeInfo.destMode = IndexToMode(changeInfo.destinationMode); d.ModesOKCancel.STModes.src.L2.rgb.value = true; d.defaultElement = d.ModesOKCancel.buttons.okBtn; d.cancelElement = d.ModesOKCancel.buttons.cancelBtn; } // end of CreateDialog // initialize variables of dialog // return false if no document to change, true if found document to change this.InitVariables = function() { // look for last used params via Photoshop registry, getCustomOptions will throw if none exist try { var desc = app.getCustomOptions("85d5fff3-b16f-432c-96e6-6dbbedbbdcda"); DescriptorToChangeInfo(changeInfo, desc, strMessage); } catch(e) { // it's ok if we don't have any options, continue with defaults } // see if I am getting descriptor parameters DescriptorToChangeInfo(changeInfo, app.playbackParameters, strMessage); // make internal state reflect saved parameters changeInfo.destMode = IndexToMode(changeInfo.destinationMode); FLAG_BITMAP = changeInfo.flagBITMAP; FLAG_GRAYSCALE = changeInfo.flagGRAYSCALE; FLAG_DUOTONE = changeInfo.flagDUOTONE; FLAG_INDEXED = changeInfo.flagINDEXED; FLAG_RGB = changeInfo.flagRGB; FLAG_CMYK = changeInfo.flagCMYK; FLAG_LAB = changeInfo.flagLAB; FLAG_MULTICHANNEL = changeInfo.flagMULTICHANNEL; // make sure to do this after get parameters if (app.documents.length <= 0) // count of documents viewed { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextNeedFile); } return false; // error, don't proceed } if ( DialogModes.ALL == app.playbackDisplayDialogs ) { var d = this.dlgMain; var drop = d.ModesOKCancel.STModes.targ.w.drp; // for easier typing // make dialog reflect saved parameters drop.selection = drop.items[changeInfo.destinationMode]; d.ModesOKCancel.STModes.src.L1.bmp.value = changeInfo.flagBITMAP; d.ModesOKCancel.STModes.src.L1.gry.value = changeInfo.flagGRAYSCALE; d.ModesOKCancel.STModes.src.L1.duo.value = changeInfo.flagDUOTONE; d.ModesOKCancel.STModes.src.L1.ixc.value = changeInfo.flagINDEXED; d.ModesOKCancel.STModes.src.L2.rgb.value = changeInfo.flagRGB; d.ModesOKCancel.STModes.src.L2.cmy.value = changeInfo.flagCMYK; d.ModesOKCancel.STModes.src.L2.lab.value = changeInfo.flagLAB; d.ModesOKCancel.STModes.src.L2.mch.value = changeInfo.flagMULTICHANNEL; } return true; // all is good, continue } // routine for running the dialog and it's interactions this.RunDialog = function () { var d = this.dlgMain; // in case hit cancel button, don't close d.ModesOKCancel.buttons.cancelBtn.onClick = function() { var dToCancel = FindDialog( this ); dToCancel.close( cancelButtonID ); rollItBack = true; } // nothing for now d.onShow = function() { } // destination dropdown handler d.ModesOKCancel.STModes.targ.w.drp.onChange = function() { var theSelection = this.selection.text; var theSelectionIndex = this.selection.index; if (theSelection != null) { // only change if selection made changeInfo.destinationMode = theSelectionIndex; changeInfo.destMode = IndexToMode(changeInfo.destinationMode); } } // the source mode buttons d.ModesOKCancel.STModes.src.L1.bmp.onClick = function() { FLAG_BITMAP = ! FLAG_BITMAP; changeInfo.flagBITMAP = FLAG_BITMAP; } d.ModesOKCancel.STModes.src.L1.gry.onClick = function() { FLAG_GRAYSCALE = ! FLAG_GRAYSCALE; changeInfo.flagGRAYSCALE = FLAG_GRAYSCALE; } d.ModesOKCancel.STModes.src.L1.duo.onClick = function() { FLAG_DUOTONE = ! FLAG_DUOTONE; changeInfo.flagDUOTONE = FLAG_DUOTONE; } d.ModesOKCancel.STModes.src.L1.ixc.onClick = function() { FLAG_INDEXED = ! FLAG_INDEXED; changeInfo.flagINDEXED = FLAG_INDEXED; } d.ModesOKCancel.STModes.src.L2.rgb.onClick = function() { FLAG_RGB = ! FLAG_RGB; changeInfo.flagRGB = FLAG_RGB; } d.ModesOKCancel.STModes.src.L2.cmy.onClick = function() { FLAG_CMYK = ! FLAG_CMYK; changeInfo.flagCMYK = FLAG_CMYK; } d.ModesOKCancel.STModes.src.L2.lab.onClick = function() { FLAG_LAB = ! FLAG_LAB; changeInfo.flagLAB = FLAG_LAB; } d.ModesOKCancel.STModes.src.L2.mch.onClick = function() { FLAG_MULTICHANNEL = ! FLAG_MULTICHANNEL; changeInfo.flagMULTICHANNEL = FLAG_MULTICHANNEL; } // all or nothing d.ModesOKCancel.STModes.src.L1.AORN.all.onClick = function() { var dThis = FindDialog( this ); SetButtons(dThis, true) } d.ModesOKCancel.STModes.src.L1.AORN.non.onClick = function() { var dThis = FindDialog( this ); SetButtons(dThis, false) } // hit OK, do mode convert d.ModesOKCancel.buttons.okBtn.onClick = function () { var dThis = FindDialog( this ); if (gMC.saveDest != changeInfo.destMode && changeInfo.modeObject != undefined ) { changeInfo.modeObject = undefined; changeInfo.modeClass = undefined; } var OKflag = MCExecute(); if (OKflag) { dThis.close(okButtonID); } } if (!this.InitVariables()) { return true; // no document to change, kick out now } // remember our starting mode this.saveDest = changeInfo.destMode; // give the hosting app the focus before showing the dialog app.bringToFront(); this.dlgMain.center(); return d.show(); } } // set all buttons on or off function SetButtons(d, OnOrOff) { FLAG_BITMAP = OnOrOff; changeInfo.flagBITMAP = FLAG_BITMAP; d.ModesOKCancel.STModes.src.L1.bmp.value = OnOrOff; FLAG_GRAYSCALE = OnOrOff; changeInfo.flagGRAYSCALE = FLAG_GRAYSCALE; d.ModesOKCancel.STModes.src.L1.gry.value = OnOrOff; FLAG_DUOTONE = OnOrOff; changeInfo.flagDUOTONE = FLAG_DUOTONE; d.ModesOKCancel.STModes.src.L1.duo.value = OnOrOff; FLAG_INDEXED = OnOrOff; changeInfo.flagINDEXED = FLAG_INDEXED; d.ModesOKCancel.STModes.src.L1.ixc.value = OnOrOff; FLAG_RGB = OnOrOff; changeInfo.flagRGB = FLAG_RGB; d.ModesOKCancel.STModes.src.L2.rgb.value = OnOrOff; FLAG_CMYK = OnOrOff; changeInfo.flagCMYK = FLAG_CMYK; d.ModesOKCancel.STModes.src.L2.cmy.value = OnOrOff; FLAG_LAB = OnOrOff; changeInfo.flagLAB = FLAG_LAB; d.ModesOKCancel.STModes.src.L2.lab.value = OnOrOff; FLAG_MULTICHANNEL = OnOrOff; changeInfo.flagMULTICHANNEL = FLAG_MULTICHANNEL; d.ModesOKCancel.STModes.src.L2.mch.value = OnOrOff; } function MCExecute() { var docRef = app.activeDocument; // for easier typing var numChannels = docRef.componentChannels.length; // number of channels in the source doc var doConversion = false; // do the mode conversion? var preConvertRGB = false; // convert to image to RGB before final conversion? var preConvertGray = false; // convert to grayscale before final? var preConvert8bit = false; // convert to 8-bit color before final? var preConvert16bit = false; // convert to 16-bit color before final? var depth = 8; // bit-depth of the current doc var userCancel = false; var hasErrorMessage = false; var errorMessage = ""; var keyTo = charIDToTypeID( 'T ' ); var eventConvertMode = charIDToTypeID( 'CnvM' ); var keyDepth = charIDToTypeID( 'Dpth' ); var colorDepthType = docRef.bitsPerChannel; // Retrieve the color depth var docMode = docRef.mode; // Retrieve the mode (DocumentMode.RGB, etc) if ( numChannels == 0 ) numChannels = docRef.channels.length; // for multichannel documents the componentChannels is 0 so use regular ol' channels instead // get bits per channel if (colorDepthType == BitsPerChannelType.EIGHT) { depth = 8; } else if (colorDepthType == BitsPerChannelType.ONE) { depth = 1; } else if (colorDepthType == BitsPerChannelType.SIXTEEN) { depth = 16; } else if (colorDepthType == BitsPerChannelType.THIRTYTWO) { depth = 32; } var targetClass = ModeUIToClass(changeInfo.destMode); if (targetClass == classNull) { return -1; } // if the doc is already in the destination mode, don't bother if (changeInfo.destMode == docMode) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextModeSame); } return false; } // tell them they have to supply at least one input mode if (!FLAG_BITMAP && !FLAG_GRAYSCALE && !FLAG_DUOTONE && !FLAG_INDEXED && !FLAG_RGB && !FLAG_CMYK && !FLAG_LAB && !FLAG_MULTICHANNEL) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextOneSrcMode); } return false; } // See if the source doc mode matches any of our source switches switch(docMode) { case DocumentMode.BITMAP: if (FLAG_BITMAP) { doConversion = true; preConvertGray = true; } break; case DocumentMode.GRAYSCALE: if (FLAG_GRAYSCALE) { doConversion = true; } break; case DocumentMode.DUOTONE: if (FLAG_DUOTONE) doConversion = true; break; case DocumentMode.INDEXEDCOLOR: if (FLAG_INDEXED) { doConversion = true; if (changeInfo.destMode == DocumentMode.BITMAP || changeInfo.destMode == DocumentMode.DUOTONE) preConvertGray = true; else if (changeInfo.destMode == DocumentMode.MULTICHANNEL) preConvertRGB = true; } break; case DocumentMode.RGB: if (FLAG_RGB) { doConversion = true; if (changeInfo.destMode == DocumentMode.BITMAP || changeInfo.destMode == DocumentMode.DUOTONE) preConvertGray = true; } break; case DocumentMode.CMYK: if (FLAG_CMYK) { doConversion = true; if (changeInfo.destMode == DocumentMode.BITMAP || changeInfo.destMode == DocumentMode.DUOTONE) preConvertGray = true; else if (changeInfo.destMode == DocumentMode.INDEXEDCOLOR) preConvertRGB = true; } break; case DocumentMode.LAB: if (FLAG_LAB) { doConversion = true; if (changeInfo.destMode == DocumentMode.BITMAP || changeInfo.destMode == DocumentMode.DUOTONE) preConvertGray = true; else if (changeInfo.destMode == DocumentMode.INDEXEDCOLOR) preConvertRGB = true; } break; case DocumentMode.MULTICHANNEL: if (FLAG_MULTICHANNEL) { doConversion = true; // if we don't have at least 3 channels, we're going to grayscale regardless if (numChannels < 3) preConvertGray = true; else { if (changeInfo.destMode == DocumentMode.DUOTONE) preConvertGray = true; else if (changeInfo.destMode == DocumentMode.CMYK) { if (numChannels < 4) preConvertRGB = true; } else if (changeInfo.destMode == DocumentMode.INDEXEDCOLOR) { preConvertRGB = true; } } } break; } // only convert depth if we have to if (depth >= 16 && (changeInfo.destMode == DocumentMode.BITMAP || changeInfo.destMode == DocumentMode.DUOTONE || changeInfo.destMode == DocumentMode.INDEXEDCOLOR) ) preConvert8bit = true; if (!preConvert8bit && depth >= 32 && (changeInfo.destMode == DocumentMode.CMYK || changeInfo.destMode == DocumentMode.LAB || changeInfo.destMode == DocumentMode.MULTICHANNEL) ) preConvert16bit = true; // condition wasn't met, so just return if (!doConversion) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextModeMatch); } return false; // fauxSPHandledErr; } var historyState = app.activeDocument.activeHistoryState; // remember current state rollItBack = false; // Force the image to 8-bit mode, if required // always do this first if (preConvert8bit) { var modeDesc8Bit = new ActionDescriptor(); modeDesc8Bit.putInteger(keyDepth, 8); var returnDesc = executeAction( eventConvertMode, modeDesc8Bit, DialogModes.NO ); if (returnDesc == classNull) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextErrIntCnv8); } rollItBack = true; return false; } } // always do this second if (preConvert16bit) { var modeDesc16Bit = new ActionDescriptor(); modeDesc16Bit.putInteger(keyDepth, 16); var returnDesc = executeAction( eventConvertMode, modeDesc16Bit, DialogModes.NO ); if (returnDesc == classNull) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextErrIntCnv16); } rollItBack = true; return false; } } // Force the image into RGB, if required if (preConvertRGB) { var modeDescRGB = new ActionDescriptor(); modeDescRGB.putClass(keyTo, classRGBColorMode); var returnDesc = executeAction( eventConvertMode, modeDescRGB, DialogModes.NO ); if (returnDesc == classNull) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextErrCvtRGB); } rollItBack = true; return false; } } // Force the image into grayscale, if required if (preConvertGray) { var modeDescGray = new ActionDescriptor(); modeDescGray.putClass(keyTo, classGrayscaleMode); var returnDesc = executeAction( eventConvertMode, modeDescGray, DialogModes.NO ); if (returnDesc == classNull) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextErrCvtGray); } rollItBack = true; return false; } } var modeDesc = new ActionDescriptor(); if (changeInfo.modeObject != undefined) { modeDesc.putObject(keyTo, changeInfo.modeClass, changeInfo.modeObject); } else { modeDesc.putClass(keyTo, targetClass); } if (changeInfo.flatten != FLATTEN_UNUSED) { modeDesc.putBoolean(keyMerge, changeInfo.flatten); } var cancelFlag = false; try { var returnDesc = executeAction( eventConvertMode, modeDesc, app.playbackDisplayDialogs ); } catch (e) { rollItBack = true; cancelFlag = true; // assume cancel } if (returnDesc == classNull) { // error, no returned descriptor (TO DO: IS THIS CORRECT?) if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(strTextErrCvtTarg); } rollItBack = true; } else if (!rollItBack) { // if completed successfully... // check for error message in returned descriptor var messageStr = ""; var hasErrorMessage = returnDesc.hasKey( keyMessage); if (hasErrorMessage) { messageStr = returnDesc.getString( keyMessage ); if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert(messageStr); } rollItBack = true; } else if ( returnDesc.hasKey( keyTo ) ) { changeInfo.modeObject = returnDesc.getObjectValue(keyTo); changeInfo.modeClass = returnDesc.getObjectType(keyTo); } } // check for cancel, error if (rollItBack) { app.activeDocument.activeHistoryState = historyState; // rollback state of document return cancelFlag; // kill dialog box if cancel } return true; } function IndexToMode(modeIndex) { var uiMode = 0; switch (modeIndex) { case 0: uiMode = DocumentMode.BITMAP; break; case 1: uiMode = DocumentMode.GRAYSCALE; break; case 2: uiMode = DocumentMode.DUOTONE; break; case 3: uiMode = DocumentMode.INDEXEDCOLOR; break; case 4: uiMode = DocumentMode.RGB; break; case 5: uiMode = DocumentMode.CMYK; break; case 6: uiMode = DocumentMode.LAB; break; case 7: uiMode = DocumentMode.MULTICHANNEL; break; } return(uiMode); } function ClassToIndex(classMode) { var uiMode = 0; switch (classMode) { case classBitmapMode: uiMode = 0; break; case classGrayscaleMode: uiMode = 1; break; case classDuotoneMode: uiMode = 2; break; case classIndexedColorMode: uiMode = 3; break; case classRGBColorMode: uiMode = 4; break; case classCMYKColorMode: uiMode = 5; break; case classLabColorMode: uiMode = 6; break; case classMultichannelMode: uiMode = 7; break; } return(uiMode); } function ModeUIToClass(uiMode) { var actionType = classNull; switch (uiMode) { case DocumentMode.BITMAP: actionType = classBitmapMode; break; case DocumentMode.GRAYSCALE: actionType = classGrayscaleMode; break; case DocumentMode.DUOTONE: actionType = classDuotoneMode; break; case DocumentMode.INDEXEDCOLOR: actionType = classIndexedColorMode; break; case DocumentMode.RGB: actionType = classRGBColorMode; break; case DocumentMode.CMYK: actionType = classCMYKColorMode; break; case DocumentMode.LAB: actionType = classLabColorMode; break; case DocumentMode.MULTICHANNEL: actionType = classMultichannelMode; break; } return(actionType); } function CheckVersion() { var numberArray = version.split("."); if ( numberArray[0] < 9 ) { if ( DialogModes.NO != app.playbackDisplayDialogs ) { alert( strMustUse ); } throw( strMustUse ); } } function FindDialog( inItem ) { var w = inItem; while ( 'dialog' != w.type ) { if ( undefined == w.parent ) { w = null; break; } w = w.parent; } return w; } /////////////////////////////////////////////////////////////////////////////// // Function: ChangeInfoToDescriptor // Usage: create an ActionDescriptor from the ChangeInfo JavaScript Object // Input: ChangeInfo JavaScript Object (o) // object unique string (s) // Return: ActionDescriptor // NOTE: We use the string id's here. They are mapped to the char id's. /////////////////////////////////////////////////////////////////////////////// function ChangeInfoToDescriptor (o, s) { var d = new ActionDescriptor; d.putString( keyMessage, s ); var l = new ActionList; if (o.flagBITMAP) l.putEnumerated( typeSourceMode, enumUIBitmap ); if (o.flagGRAYSCALE) l.putEnumerated( typeSourceMode, enumUIGrayscale ); if (o.flagDUOTONE) l.putEnumerated( typeSourceMode, enumUIDuotone ); if (o.flagINDEXED) l.putEnumerated( typeSourceMode, enumUIIndexed ); if (o.flagRGB) l.putEnumerated( typeSourceMode, enumUIRGB ); if (o.flagCMYK) l.putEnumerated( typeSourceMode, enumUICMYK ); if (o.flagLAB) l.putEnumerated( typeSourceMode, enumUILab ); if (o.flagMULTICHANNEL) l.putEnumerated( typeSourceMode, enumUIMultichannel ); if (l.count) d.putList( keySourceMode, l ); if (o.modeObject instanceof ActionDescriptor) d.putObject( keyDestinationMode, o.modeClass, o.modeObject ); else d.putClass( keyDestinationMode, ModeUIToClass( o.destMode ) ); if (o.flatten != FLATTEN_UNUSED) d.putBoolean( keyMerge, o.flatten ); return d; } /////////////////////////////////////////////////////////////////////////////// // Function: DescriptorToChangeInfo // Usage: update a JavaScript Object from an ActionDescriptor // Input: JavaScript Object (o), current object to update (output) // Photoshop ActionDescriptor (d), descriptor to pull new params for object from // object unique string (s) // Return: Nothing, update is applied to passed in JavaScript Object (o) /////////////////////////////////////////////////////////////////////////////// function DescriptorToChangeInfo (o, d, s) { if ( d.hasKey(keyMessage) && ( s != d.getString(keyMessage) )) return; if ( d.hasKey( keySourceMode ) ) { // if the value is present it means true // first we false out all the params // then read in each one in the list o.flagBITMAP = false; o.flagGRAYSCALE = false; o.flagDUOTONE = false; o.flagINDEXED = false; o.flagRGB = false; o.flagCMYK = false; o.flagLAB = false; o.flagMULTICHANNEL = false; var l = d.getList( keySourceMode ); var c = l.count; for ( var i = 0; i < c; i++ ) { switch ( l.getEnumerationValue( i ) ) { case enumUIMultichannel: o.flagMULTICHANNEL = true; break; case enumUILab: o.flagLAB = true; break; case enumUICMYK: o.flagCMYK = true; break; case enumUIRGB: o.flagRGB = true; break; case enumUIIndexed: o.flagINDEXED = true; break; case enumUIDuotone: o.flagDUOTONE = true; break; case enumUIGrayscale: o.flagGRAYSCALE = true; break; case enumUIBitmap: o.flagBITMAP = true; break; } } } if ( d.hasKey( keyMerge ) ) o.flatten = d.getBoolean( keyMerge ); if ( d.hasKey( keyDestinationMode ) ) { if ( DescValueType.CLASSTYPE == d.getType( keyDestinationMode ) ) { var targetClass = d.getClass( keyDestinationMode ); o.destinationMode = ClassToIndex( targetClass ); o.destMode = IndexToMode(o.destinationMode); } else { o.modeClass = d.getObjectType( keyDestinationMode ); o.modeObject = d.getObjectValue( keyDestinationMode ); o.destinationMode = ClassToIndex( o.modeClass ); o.destMode = IndexToMode(o.destinationMode); } } } /////////////////////////////////////////////////////////////////////////////// // Function: ChangeInfo // Usage: object for holding the parameters // Input: // Return: object holding the mode change parameters /////////////////////////////////////////////////////////////////////////////// function ChangeInfo() { this.destinationMode = 5; this.destMode = IndexToMode( this.destinationMode ); this.flagBITMAP = FLAG_BITMAP; this.flagGRAYSCALE = FLAG_GRAYSCALE; this.flagDUOTONE = FLAG_DUOTONE; this.flagINDEXED = FLAG_INDEXED; this.flagRGB = FLAG_RGB; this.flagCMYK = FLAG_CMYK; this.flagLAB = FLAG_LAB; this.flagMULTICHANNEL = FLAG_MULTICHANNEL; this.flatten = FLATTEN_UNUSED; // Flatten the image, start in unused state // create these undefined this.modeObject; this.modeClass; } // Conditional Mode Change.jsx