/* Show Image Properties 1.3
∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
An InDesign CS2-CS3 JavaScript
OS: Mac OS X, Windows XP.
∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
Скрипт предназначен для отображения свойств выделенного изображения InDesign-документа.
Реализована возможность открытия векторных изображений программой "Adobe Illustrator", растровых - "Adobe Photoshop".
Установленные программы Photoshop, Illustrator и InDesign должны быть одной версии Creative Suite (CS).

Отображаются свойства:
● имя, путь файла (если изображение не было вставлено через буфер обмена),
● состояние связи с файлом,
● тип изображения, 
● название программы, в которой создавался файл (creator),
● автор файла (author, при наличии данных),
● цветовое пространство (color space), 
● профиль, 
● эффективное разрешение  (effective resolution),
● физическое разрешение (native resolution, actual, Ppi),
● значения горизонтального и вертикального масштабирования,
● углы поворота и сдвига: Rotatation Angle, Shear Angle (если значение не равно 0°);
● тип Clipping Path и имя используемого альфа-канала или пути (в зависимости от установок),
● состояние атрибута «Nonprinting»,
● Blending Settings (если Opacity < 100% или Blending Mode не соответствует «Normal»).
∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
© 2008 Дмитрий Лапаев 
(d.lapaev@univest-prepress.com, d.lapaev@gmail.com).
*/
with (app)
{
	const myScriptVer = "1.3";
	const myScriptName = "Show Image Properties " + myScriptVer;
	const myNullLinkImage = "Image without link";
	// определение версии InDesign
	try{const InDver = version.substr(0,1);}
	catch(e){alert(myScriptName + "\nis not compatible with this version of InDesign!"); exit();}
	if (documents.length == 0) {alert(myScriptName + "\nPlease open a document, select an image, and try again."); exit();}
	if (selection.length != 1) {alert(myScriptName + "\nPlease select an image and try again."); exit();}
	// проверяем выделенный объект
	var SImage = SEL_IMAGE(selection[0]);
	if (SImage == false) {alert (myScriptName + "\nSelect only image!"); exit();}
	// отображаем cвойства изображения
	ImagePropertiesShow (SImage);
exit();
}

// Функции	∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙
/* Функция проверки выленного объекта.
Возвращает выделенное изображение.
"false" - при выделенном объекте, который не содержит изображений.
*/
function SEL_IMAGE (SelObj)
{
	var Result = false;
	var SelConstrName = SelObj.constructor.name;
	if (SelConstrName == "Image" | SelConstrName == "EPS" | SelConstrName == "PDF" | SelConstrName == "WMF" | SelConstrName == "PICT") Result = SelObj;
	else if  (SelConstrName == "Rectangle" | SelConstrName == "Oval" | SelConstrName == "Polygon" )
		{
			var NGphcs = SelObj.allGraphics.length;
			if (NGphcs  > 0) Result = SelObj.allGraphics[0];
		}
return Result
}

/* Функция выполняет поиск "истинности" атрибута Nonprinting 
для изображения и групп, включающих текущий объект. */
function myNonprint_ParentRe (myGraphNObj)
{
	try 
		{	
			var mNonPrRes = myGraphNObj.nonprinting;
			// условие рекурсивного вызова функции
			if (mNonPrRes == false) 
				{
					mNonPrRes = myNonprint_ParentRe (myGraphNObj.parent);
					if(mNonPrRes == true) return true;
				}
			else return true;
		} 	
catch (e) {return false;} 
}

/* Функция отменяет "истинность" атрибута Nonprinting 
для изображения, его контейнера и групп, включающих текущий объект. */
function myNonpFalse_ParentRe (myGraphFObj)
{
try 
	{	
		myGraphFObj.nonprinting = false;
		myNonpFalse_ParentRe(myGraphFObj.parent);
	} 	catch (e) {} 
}

/* Функция определения параметров изображения.
Возвращает массив RVPpiProf.
*/
function RastrPPIimposProfile (myL_Image)
{
	var RVPpiProf = new Array();
	// 1) связь с файлом
	var myLinkObj = null;
	var myLinkObjCreator = "";
	var myLinkObjAuthor = "";
	try {myLinkObj = myL_Image.itemLink; myLinkObjCreator = myLinkObj.linkXmp.creator; myLinkObjAuthor = myLinkObj.linkXmp.author;} 
	catch (e) {}	
	var CurrentImageSpace = "N/A";
	var ImageRastrType = true;	
	// 2) цветовое пространство изображения 
	try 
		{  
			CurrentImageSpace = myL_Image.space;
			// если нет ошибки,  то считаем что изображение является растровым
		}
	catch (e) 
		{ 
			if (!findWord_inStr(myLinkObjCreator, "Photoshop")) ImageRastrType = false;
			// если не определяется цветовое пространство 
			// и в названии программы, создавшей изображение, не найдено "Photoshop", то считаем изображение векторным
		}
	// 3) физическое и эффективное разрешение   
	var PPIimpos = true;	
	var EffPpi1 = "N/A";
	var EffPpi2 = "N/A";
	var actPpi1 = "N/A";
	var actPpi2 = "N/A";
	try 
		{ 
			actPpi1 = myL_Image.actualPpi[0];
			actPpi2 = myL_Image.actualPpi[1];
			EffPpi1 = myL_Image.effectivePpi[0];
			EffPpi2 = myL_Image.effectivePpi[1];
		}
	catch (e) {PPIimpos = false;}
	// 4) встроенный профиль
	var ProfileSts = "";
	try {ProfileSts = myL_Image.profile;}
	catch (e) {ProfileSts = "N/A";}
	// тип изображения
	var CurrentImageType = myL_Image.imageTypeName;
	if (CurrentImageType == "") CurrentImageType = myL_Image.constructor.name;
	// атрибут "не печатать"
	var myImNonprint = myNonprint_ParentRe (myL_Image);
	// clipping Path & applied Path Name
	var myImClippingType = myImageClippingPath(myL_Image);
	// alpha Channels Names
	var myImAlphaChNames = myL_Image.clippingPath.alphaChannelPathNames.length;
	for (var ACc = 0; ACc < myL_Image.clippingPath.alphaChannelPathNames.length; ACc++)
	myImAlphaChNames += ", " + myL_Image.clippingPath.alphaChannelPathNames[ACc];
	// photoshop Paths Names
	var myImPhPathNames = myL_Image.clippingPath.photoshopPathNames.length;
	for (ACc = 0; ACc < myL_Image.clippingPath.photoshopPathNames.length; ACc++)
	myImPhPathNames += ", " + myL_Image.clippingPath.photoshopPathNames[ACc];
	// масштабирование
	var VertScaleObj = String (myL_Image.verticalScale).substr (0,7);
	var HorzScaleObj = String (myL_Image.horizontalScale).substr (0,7);
	// углы
	var ARotateAngleObj;
	if (Math.abs (myL_Image.rotationAngle) > 0.0001) ARotateAngleObj= String (myL_Image.rotationAngle).substr (0,6);
	else ARotateAngleObj = 0;
	var AShearAngleObj;
	if (Math.abs (myL_Image.shearAngle) > 0.0001) AShearAngleObj= String (myL_Image.shearAngle).substr (0,5);
	else AShearAngleObj = 0;
	// заполняем массив полученными данными 
	RVPpiProf.push(ImageRastrType);						// 	RVPpiProf [00]	- boolean, тип объекта: для растрового - "true"
	RVPpiProf.push(PPIimpos);									//	RVPpiProf [01]	- boolean, возможность получения данных об эффективном разрешении
	RVPpiProf.push(ProfileSts);								//	RVPpiProf [02]	- string, информация о цветовом профиле 
	RVPpiProf.push(CurrentImageSpace);					//	RVPpiProf [03]	- цветовое пространство 
	RVPpiProf.push(EffPpi1);									//	RVPpiProf [04]	- эффективное разрешение (горизонтальное)
	RVPpiProf.push(EffPpi2);									//	RVPpiProf [05]	- эффективное разрешение (вертикальное)
	RVPpiProf.push(CurrentImageType);					//	RVPpiProf [06]	- тип изображения
	RVPpiProf.push(HorzScaleObj);							//	RVPpiProf [07]	- значение масштабирования по горизонтали (%)
	RVPpiProf.push(VertScaleObj);							//	RVPpiProf [08]	- значение масштабирования по вертикали (%)
	RVPpiProf.push(myImNonprint);							//	RVPpiProf [09]	- boolean, при "true" - не печатать изображение
	RVPpiProf.push(myLinkObj);								//	RVPpiProf [10]	- item Link
	RVPpiProf.push(myImClippingType);					//	RVPpiProf [11]	- тип Clipping Path изображения
	RVPpiProf.push(ARotateAngleObj);						//	RVPpiProf [12]	- значение угла поворота Rotation Angle
	RVPpiProf.push(AShearAngleObj);						//	RVPpiProf [13]	- значение Shear Angle
	RVPpiProf.push(actPpi1);									//	RVPpiProf [14]	- физическое разрешение разрешение (горизонтальное)
	RVPpiProf.push(actPpi2);									//	RVPpiProf [15]	- физическое разрешение (вертикальное)
	RVPpiProf.push(myImAlphaChNames);				// 	RVPpiProf [16]	- количество, названия альфа-каналов
	RVPpiProf.push(myImPhPathNames);					// 	RVPpiProf [17]	- количество, названия путей 
	RVPpiProf.push(myLinkObjCreator);					// 	RVPpiProf [18]	- имя программы, в которой создавался файл изображения
	RVPpiProf.push(myLinkObjAuthor);						// 	RVPpiProf [19]	- автор
return RVPpiProf;	
}

/* Функция отображения свойств. */
function ImagePropertiesShow (mySelectImage)
{
	var myLinksStatus = new Array (["Normal", 1852797549], ["Modified", 1819242340], ["Missing", 1819109747], ["Embedded", 1282237028]);
	// определяем свойства изоображения
	var ObjParams = RastrPPIimposProfile (mySelectImage);
	// формируем текстовую строку с параметрами изображения
	var myImageInfo = "";
	// состояние связи
	var MyLinkStatus = "";
	var myImageName = myNullLinkImage;
	if (ObjParams[10] != null) 
		{
			myImageName = ObjParams[10].name;
			for (var myLSc = 0; myLSc < myLinksStatus.length; myLSc++) 
			if (ObjParams[10].status == myLinksStatus[myLSc][1]) {var MyLinkStatus = "\n\nLink Status: " + myLinksStatus[myLSc][0] + "\n"; break}
			if (File.fs == "Macintosh") myImageInfo += "File: \"" + ObjParams[10].name + "\"\nPath: " +  ObjParams[10].filePath + MyLinkStatus + "\n";
			else myImageInfo += "File: \"" + ObjParams[10].name + "\"\nPath: " +  myRowsFromStr(File(ObjParams[10].filePath).fsName, 60) + MyLinkStatus + "\n";
		}
	else myImageInfo += myNullLinkImage + ":\n\n";
	// тип изображения
	myImageInfo += "● Type: " + ObjParams[6] + "\n";
	// creator
	if (ObjParams[18] != "") myImageInfo += "● Creator: " + ObjParams[18] + "\n";
	// автор
	if (ObjParams[19] != "") myImageInfo += "● Author: " + ObjParams[19] + "\n";
	// цветовое пространство изображения
	myImageInfo += "● Color Space: " + ObjParams[3]  + "\n";
	// выбор программы для открытия файла
	var myImageOpenProgram = "";
	if (ObjParams[0] == false) {myImageOpenProgram = "Adobe Illustrator";}
	else {myImageOpenProgram = "Adobe Photoshop";}
	// информация о профиле изображения (image color settings)
	myImageInfo += "● Profile: " + ObjParams[2] + "\n";
	// разрешение
	if (ObjParams[1] == true)
		{	
			myImageInfo += "● Effective Resolution: "+ ObjParams[4] + "x" + ObjParams[5] +" Ppi\n";
			myImageInfo += "● Native Resolution: "+ ObjParams[14] + "x" + ObjParams[15] +" Ppi\n";
		}
	// масштабирование
	myImageInfo += "● Scale: horizontal "+ ObjParams[7] + "% , vertical "+ ObjParams[8] + "%\n";
	// углы: Rotation Angle, Shear Angle
	if (ObjParams[12] != 0) myImageInfo += "● Rotation Angle: "+ ObjParams[12] + "°\n";
	if (ObjParams[13] != 0) myImageInfo += "● Shear Angle: "+ ObjParams[13] + "°\n";
	// Clipping Path Type
	myImageInfo += "● Clipping Path Type: " + ObjParams [11] + "\n";
	if (ObjParams[16] != 0) myImageInfo += "● Alpha Channels: " + ObjParams [16] + "\n";
	if (ObjParams[17] != 0) myImageInfo += "● Photoshop Paths: " + ObjParams [17] + "\n";
	// атрибут "Nonprinting"
	if (ObjParams[9] == true)
	if (confirm("Set attribute Nonprinting to Off?", "", myImageName) == true) {myNonpFalse_ParentRe (mySelectImage);}
	if (myNonprint_ParentRe (mySelectImage) == true) myImageInfo += "● Print: Off\n"; else  myImageInfo += "● Print: On\n";
	// установки прозрачности - Blending Settings
	myImageInfo += OBJ_Effects (mySelectImage, InDver);
	// отображаем информацию 
	if (ObjParams[10] != null) 
		{
			if (ObjParams[10].status == 1852797549 | ObjParams[10].status == 1819242340 )
				{
					if (confirm (myImageInfo + "\nOpen this file with " + myImageOpenProgram + " ?", "", "Image Properties " + myScriptVer) == true)
						{	
							if (ObjParams[0] == true) // растровое изображение
								try{
								/* открываем файл программой Adobe Photoshop */
								photoshop.open(File(ObjParams[10].filePath));}
								catch (e) {alert(e + "\nAdobe Photoshop is not Installed!", "", true)}
							else
								try{
								/* открываем файл программой Adobe Illustrator */
								illustrator.open(File(ObjParams[10].filePath));}
								catch (e) {alert(e + "\nAdobe Illustrator is not Installed!", "", true)}
						}
				}
			else alert (myImageInfo, "Image Properties " + myScriptVer, false);
		}
	else alert (myImageInfo, "Image Properties " + myScriptVer, false);
}

/* Функция анализа  установок прозрачности.
Анализируется непрозрачность (Opacity) и режимы наложения (Blending Mode).
Возвращает текстовую информацию установок прозрачности изображения и его контейнера
при условиях: Opacity < 100% или Blending Mode - не "Normal".
*/
function OBJ_Effects (TranspCh_obj, myInDesignversion)
{
	var TranspSetStr = "";
	// условие - при генерации ошибки завершение (отсекание рекурсии)
	if (myInDesignversion != 4)
		try {var eff_obj = TranspCh_obj.transparencySettings.blendingSettings; var ImageBMode = eff_obj.blendMode;}
		catch(e) {return TranspSetStr;}
	else 
		try {var eff_obj = TranspCh_obj; var ImageBMode = eff_obj.blendMode;}
		catch(e) {return TranspSetStr;}
	var ImageOpac = eff_obj.opacity;
	var IBl = eff_obj.isolateBlending;
	var KG = eff_obj.knockoutGroup;
	if (IBl == true) IBl = "On"; else IBl = "Off";
	if (KG == true) KG = "On"; else KG = "Off";
	// Заполняем массив значений Blending Mode
	var MBlendMods = new Array([1852797549, "Normal"], [2020625762, "Multiply"], [2020625763, "Screen"], [2020625764, "Overlay"], 
	[2020625765, "Soft Light"], [2020625766, "Hard Light"], [2020625767, "Color Dodge"], [2020625768, "Color Burn"], [2020625769, "Darken"], 
	[2020625770, "Lighten"], [2020625771, "Difference"], [2020625772 , "Exclusion"], [2020625773, "Hue"], [1380545377, "Saturation"], 
	[1668246642, "Color"], [2020625776, "Luminosity"]);
	// проверка Opacity и Blending Mode 
	if (ImageBMode != 1852797549 | ImageOpac != 100)
		{
			for (var bm = 0; bm < MBlendMods.length; bm++) 
			if (ImageBMode == MBlendMods[bm][0]) var bmText = MBlendMods[bm][1];		
			TranspSetStr += TranspCh_obj.constructor.name + ":\n● Opacity: " + ImageOpac + "%\n● Blending Mode: \"" + bmText + 
			"\"\n● Isolate Blending: " + IBl + "\n● Knockout Group: " + KG + "\n";
		}
	// рекурсивный вызов
	TranspSetStr += OBJ_Effects (TranspCh_obj.parent, myInDesignversion);
return TranspSetStr;
}

/* Функция определения типа Clipping Path изображения. */	
function myImageClippingPath(myGrImage)
{
	var myClippingPathTypes = new Array(["None", 1852796517], ["Detect Edges", 1685349735], ["Alpha Channel", 1634756707], ["Photoshop Path", 1886613620], ["User-modified Path", 1970106484]);
	var myObjClipPath = myGrImage.clippingPath.clippingType;
	for (var cpt = 0; cpt < myClippingPathTypes.length; cpt++)
	if (myObjClipPath == myClippingPathTypes[cpt][1]) var myCPtypeStr = myClippingPathTypes[cpt][0];
	if (myGrImage.clippingPath.appliedPathName != "") myCPtypeStr += ", " + myGrImage.clippingPath.appliedPathName;
return myCPtypeStr;
}

/* Функция разбивает путь файла на несколько строк  по  numbCh символов. */	
function myRowsFromStr(myStrVal, numbCh)
{
	var myNewRStr = "";
	var RowsCounter = 1;
	myStrVal = String(myStrVal);
	var ctx = 0;
	while (ctx < myStrVal.length)
		{	
			if (ctx == numbCh * RowsCounter) {myNewRStr += "\n";  RowsCounter++;}
			myNewRStr += myStrVal[ctx];
			ctx++;
		}
return myNewRStr;
}

/* Функция возвращает истинность при обнаружении слова myWord в строке myT_String. */	
function findWord_inStr(myT_String, myWord)
{
	myT_String = String(myT_String);
	var myWrdLength = myWord.length;
	for (var chCnt = 0; chCnt < myT_String.length; chCnt++)
	{if (myT_String[chCnt] == myWord[0] & myT_String.substr(chCnt, myWrdLength) == myWord) return true}
return false;
}

// 27 января 2008 года