Script to Align Text layer to center of another reference layer - photoshop-script

The contents to the text layer are added from csv import. Some are short length and some are long, contain 2 words and take up 2 lines in the layer. What I need is after the content is added, the layer should be horizontally and vertically aligned to another layer. I want to do this alignment using a script.
var doc = app.activeDocument;
var grps = doc.layerSets;
var pnamegrp = grps.getByName('Group 1');
var childlyr = pnamegrp.layers.getByName('child');
childlyr.textItem.contents = pname; //come from a csv file
var parentlyr= pnamegrp.layers.getByName('ReferenceRectangle');
Align_HorizCenter_VerticalCenter_withreference( childlyr , parent);
function Align_HorizCenter_VerticalCenter_withreference( child, parent){
//need help to write this
}
I am using Photoshop cc 2015 and JavaScript jsx file scripting.

Just incase somebody is looking for a solution. Translate is the method to move layer. The number of pixels to be moved can be determined by the difference in the width between the target and reference layer.
var startRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.INCHES;
var doc = app.activeDocument;
var grps = doc.layerSets;
var pnamegrp = grps.getByName('Group 1');
var pnamelyr= pnamegrp.layers.getByName('pname'); //target
var pnameREF = pnamegrp.layers.getByName('Rectangle 1'); //reference var LB = pnameREF.bounds;
var RWidth = (LB[2].value) - (LB[0].value);
var RHeight = (LB[3].value) - (LB[1].value);
pnamelyr.textItem.contents = pnamearr[i];
LB = pnamelyr.bounds;
TWidth = (LB[2].value) - (LB[0].value);
THeight = (LB[3].value) - (LB[1].value);
var OffsetX = (RWidth - TWidth)/2;
var OffsetY = (RHeight - THeight)/2;
pnameTGT.translate(OffsetX,OffsetY); //move layer by offset pixels from the current position

Related

AmCharts: Data grouping for very large data sets

I am using amcharts line chart.
I have data for last 24 hours and its recorded for every seconds.
I am trying to group data in amcharts but it displays only 2 data points on chart.
1 data point is from yesterday and 1 from today.
Here is my code:
var multiLineChart = am4core.create(
"multilineChartdiv",
am4charts.XYChart
);
multiLineChart.paddingRight = 20;
multiLineChart.data = historicalData;
var dateAxis1 = multiLineChart.xAxes.push(new am4charts.DateAxis());
dateAxis1.renderer.grid.template.location = 0;
dateAxis1.minZoomCount = 1;
dateAxis1.renderer.minGridDistance = 60;
// dateAxis1.baseInterval = {
// timeUnit: "minute",
// count: 5,
// };
// this makes the data to be grouped
dateAxis1.groupData = true;
dateAxis1.groupCount = 500;
var valueAxis = multiLineChart.yAxes.push(new am4charts.ValueAxis());
var series1 = multiLineChart.series.push(new am4charts.LineSeries());
series1.dataFields.dateX = "date";
series1.dataFields.valueY = "heartRate";
series1.tooltipText = "{valueY}";
series1.tooltip.pointerOrientation = "vertical";
series1.tooltip.background.fillOpacity = 0.5;
multiLineChart.cursor = new am4charts.XYCursor();
multiLineChart.cursor.xAxis = dateAxis1;
var scrollbarX = new am4core.Scrollbar();
scrollbarX.marginBottom = 20;
multiLineChart.scrollbarX = scrollbarX;
I need to show data points for at least every 5 or 10 minutes.
If your timestamp is a string, make sure the inputDateFormat is set to match your date format as documented here as the default format is yyyy-MM-dd, truncating everything else to look like daily data, similar to your screenshot:
chart.dateFormatter.inputDateFormat = 'yyyy-MM-dd HH:mm:ss' //adjust as needed
Since your data is in seconds, it is also recommended to set the baseInterval accordingly to also ensure that your data is rendered correctly.
dateAxis1.baseInterval = {
timeUnit: "second",
count: 1,
};

Import random columns from spreadsheet into order in new spreadsheet

I'm trying to code a script that imports specific columns for a spreadsheet to another spreadsheet. However, currently i'm writing/reading every column separately, which takes quite a while. I do this because I don't need all the columns from the original sheet into the new sheet. I was wondering if my current script could be changed to get to a script where you once read the necessary columns and write them all together? I tried to search for the same but the different order of the columns and the need for specific columns makes it hard.
I hope someone could help me get to the answer.
Thanks in advance,
Tim
function getPDdataupper() {
var sheet = SpreadsheetApp.getActive().getSheetByName('SPR');
var Num = Browser.inputBox("What URL are do you want to copy from?");
var ssraw = SpreadsheetApp.openById(Num);//put Address in here*****
var sheetraw = ssraw.getSheetByName("SPR");
sheet.getRange(10,11,(sheet.getLastRow())-9,3).clearContent();
sheet.getRange(10,1,(sheet.getLastRow())-9,3).clearContent();
//ADJUST ROW
var lastrow = sheet.getLastRow()-10;
var lastrowcopiedsheet = sheetraw.getLastRow()-10;
var diff = lastrowcopiedsheet - lastrow;
if(diff > 0){sheet.insertRowsAfter(11,diff);}
if(diff < 0){sheet.deleteRows(20,(diff*-1)); }
sheet.getRange(11,1,(sheet.getLastRow())-11,33).clearContent();
var values = sheetraw.getRange(1,1,5,1).getValues();
sheet.getRange(1,1,5,1).setValues(values);
var values = sheetraw.getRange(10,3,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,2,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,38,sheetraw.getLastRow()-9,2).getValues();
sheet.getRange(10,3,(sheet.getLastRow()-9),2).setValues(values);
var values = sheetraw.getRange(10,43,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,6,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,44,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,5,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,6,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,7,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,54,sheetraw.getLastRow()-9,2).getValues();
sheet.getRange(10,8,(sheet.getLastRow()-9),2).setValues(values);
var values = sheetraw.getRange(10,58,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,10,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,14,sheetraw.getLastRow()-9,19).getValues();
sheet.getRange(10,14,(sheet.getLastRow()-9),19).setValues(values);
var values = sheetraw.getRange(10,51,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,33,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,62,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,34,(sheet.getLastRow()-9),1).setValues(values);
var values = sheetraw.getRange(10,4,sheetraw.getLastRow()-9,1).getValues();
sheet.getRange(10,35,(sheet.getLastRow()-9),1).setValues(values);
I have sorted it myself now. For someone who is looking for the same thing, please see the code below. If anyone else thinks of something better please feel free to amend.
function getPDdataupper() {
var sheet = SpreadsheetApp.getActive().getSheetByName('SPR');
var folder= DriveApp.getFolderById('FolderID');
var files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
var ssraw = SpreadsheetApp.open(files.next());
//var ssraw = SpreadsheetApp.open(Num);
}
sheet.getRange(11,1,(sheet.getLastRow())-10,53).clearContent();
var sheetraw = ssraw.getSheetByName("SPR");
sheet.getRange(10,11,(sheet.getLastRow())-9,3).clearContent();
sheet.getRange(10,1,(sheet.getLastRow())-9,3).clearContent();
//ADJUST ROW
var lastrow = sheet.getLastRow()-10;
var lastrowcopiedsheet = sheetraw.getLastRow()-10;
var diff = lastrowcopiedsheet - lastrow;
if(diff > 0){sheet.insertRowsAfter(11,diff);}
if(diff < 0){sheet.deleteRows(20,(diff*-1)); }
//var values = sheetraw.getRange(10,("C10:C,AL10:AM,AQ10:AR,F10:F,BB10:BC,BF10:BF"),(sheetraw.getLastRow()-9),53).getValues();
//sheet.getRange(10,2,(sheet.getLastRow()-9),(sheet.getLastColumn()-1)).setValues(values);
var data = sheetraw.getDataRange().getValues();{
var target = new Array();
for(n=0;n<data.length;++n){
target.push( [[data[n][2]], [data[n][37]], [data[n][38]], [data[n][43]], [data[n][42]], [data[n][5]], [data[n][53]], [data[n][54]], [data[n][57]]] );
}
sheet.getRange(1,2,target.length,target[0].length).setValues(target);
}

NSBitmapImageRep.bitmapImageRepByConvertingToColorSpace() calling deprecated CGContextClear

I'm trying to use
NSBitmapImageRep.bitmapImageRepByConvertingToColorSpace(NSColorSpace.genericRGBColorSpace(), renderingIntent: NSColorRenderingIntent.Perceptual);
to convert an NSImage to a format that can be handled by openGL, and it works (unlike bitmapImageRepByRetaggingWithColorSpace()), but I get an error:
<Error>: The function ‘CGContextClear’ is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
which is sort of useless, because it's Apple's own code, and I can't seem to find an alternative to bitmapImageRepByConvertingToColorSpace(), or any note that it too is deprecated.
EDIT:
var image=NSImage(size: frame);
image.lockFocus();
//println("NSImage: \(image.representations)");
string.drawAtPoint(NSMakePoint(0.0,0.0), withAttributes: attribs);
var bitmap2=NSBitmapImageRep(focusedViewRect: NSMakeRect(0.0,0.0,frame.width,frame.height))?;
image.unlockFocus();
bitmap=bitmap2!.bitmapImageRepByConvertingToColorSpace(NSColorSpace.genericRGBColorSpace(), renderingIntent: NSColorRenderingIntent.Perceptual);
For some reason this question interested me. It looks like the solution is to lock focus on your NSImage, then use NSBitmapImageRep(focusedViewRect:) to create the NSBitmapImageRep.
I tried to recreate your situation (as I understand it) and then create an NSBitmapImageRep with the following code:
var img:NSImage = NSImage(size: NSMakeSize(200,200))
img.lockFocus()
let testString:NSString = "test String"
testString.drawAtPoint(NSMakePoint(10,10), withAttributes: nil)
img.unlockFocus()
println("img Description = \(img.description)")
I got the following description:
img Description = NSImage 0x608000067ac0 Size={200, 200} Reps=(
"NSCGImageSnapshotRep:0x61000007cf40 cgImage=CGImage 0x6100001a2bc0")
I then extended this code to:
var img:NSImage = NSImage(size: NSMakeSize(200,200))
img.lockFocus()
let testString:NSString = "test String"
testString.drawAtPoint(NSMakePoint(10,10), withAttributes: nil)
img.unlockFocus()
println("img Description = \(img.description)")
img.lockFocus()
var bitmapRep:NSBitmapImageRep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0.0, 0.0, img.size.width, img.size.height))!
img.unlockFocus()
println("bitmap data planes = \(bitmapRep.bitmapData)")
println("bitmap pixels wide = \(bitmapRep.size.width)")
println("bitmap pixels high = \(bitmapRep.size.height)")
println("bits per sample = \(bitmapRep.bitsPerSample)")
println("samples per pixel = \(bitmapRep.samplesPerPixel)")
println("has alpha = \(bitmapRep.alpha)")
println("is planar = \(bitmapRep.planar)")
println("color space name = \(bitmapRep.colorSpace)")
println("bitmap format = \(bitmapRep.bitmapFormat)")
println("bytes per row = \(bitmapRep.bytesPerRow)")
println("bits per pixel = \(bitmapRep.bitsPerPixel)")
The output for the NSBitmapImageRep parameters was:
bitmap data planes = 0x000000010b6ff100
bitmap pixels wide = 200.0
bitmap pixels high = 200.0
bits per sample = 8
samples per pixel = 4
has alpha = true
is planar = false
color space name = Color LCD colorspace
bitmap format = C.NSBitmapFormat
bytes per row = 800
bits per pixel = 32
I've posted some new code below. I've created two NSBitMapImageRep just like your code (except that I used the method bitmapImageRepByRetaggingWithColorSpace), and I exported both of them to a PNG file. I got the same image in both PNG files.
But I'm wondering a couple of things. First, the difference in your two tests was not only the OS X version, but the hardware produced different color spaces. You should check to be sure bitmap2 is not nil.
Second, I'm wondering if OpenGL cares. If bitmap2 is not nil and you pass OpenGL bitmap2.bitmapData, does it work?
My new code (deleting most of the println):
var img:NSImage = NSImage(size: NSMakeSize(200,200))
img.lockFocus()
let testString:NSString = "test String"
let font:NSFont = NSFont(name: "AppleCasual", size: 18.0)!
let textStyle = NSMutableParagraphStyle.defaultParagraphStyle().mutableCopy() as NSMutableParagraphStyle
textStyle.alignment = NSTextAlignment.LeftTextAlignment
let textColor:NSColor = NSColor(calibratedRed: 1.0, green: 0.0, blue: 1.0, alpha: 1.0)
let attribs:NSDictionary = [NSFontAttributeName: font,
NSForegroundColorAttributeName: textColor,
NSParagraphStyleAttributeName: textStyle]
testString.drawAtPoint(NSMakePoint(0.0, 0.0), withAttributes: attribs)
img.unlockFocus()
println("img Description = \(img.description)")
img.lockFocus()
var bitmapRep:NSBitmapImageRep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0.0, 0.0, img.size.width, img.size.height))!
img.unlockFocus()
let pngPath:String = "TestStringBeforeChange.png"
let imageProps = [NSImageCompressionFactor: NSNumber(float: 1.0)]
let outputImageData = bitmapRep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: imageProps)
let fileSavePanel = NSSavePanel()
fileSavePanel.nameFieldStringValue = pngPath
var savePanelReturn = fileSavePanel.runModal()
if savePanelReturn == NSFileHandlingPanelOKButton
{
var theFileURL = fileSavePanel.URL
var saveStatus = outputImageData?.writeToURL(theFileURL!, atomically: true)
}
let bitmapRep2 = bitmapRep.bitmapImageRepByRetaggingWithColorSpace(NSColorSpace.genericRGBColorSpace())
let pngPath2:String = "TestStringAfterChange.png"
let outputImageData2 = bitmapRep2!.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: imageProps)
let fileSavePanel2 = NSSavePanel()
fileSavePanel2.nameFieldStringValue = pngPath2
var savePanel2Return = fileSavePanel2.runModal()
if savePanel2Return == NSFileHandlingPanelOKButton
{
var theFileURL2 = fileSavePanel2.URL
var saveStatus2 = outputImageData2?.writeToURL(theFileURL2!, atomically: true)
}
Sorry for all the posts, but I don't want to let this go, and it's interesting.
I created 3 PNG files: the first using the original NSBitmapImageRep, a second using an NSBitmapImageRep created with bitmapImageRepByRetaggingWithColorSpace and a third using an NSBitmapImageRep created with bitmapImageRepByConvertingToColorSpace (I, of course, got the system warning when I used this function).
Looking at these three PNG files in Preview's Inspector, they were all RGB color models; only the colorSynch profile for the first file was different from that of the second and third file. So I thought maybe there's no difference in the bitmapData among these files.
I then wrote some code to compare the bitmapData:
var firstRepPointer:UnsafeMutablePointer<UInt8> = bitmapRep.bitmapData
var secondRepPointer:UnsafeMutablePointer<UInt8> = bitmapRep2!.bitmapData
var firstByte:UInt8 = 0
var secondByte:UInt8 = 0
for var i:Int = 0; i < 200; i++
{
for var j:Int = 0; j < 200; j++
{
for var k:Int = 0; k < 4; k++
{
memcpy(&firstByte, firstRepPointer, 1)
firstRepPointer += 1
memcpy(&secondByte, secondRepPointer, 1)
secondRepPointer += 1
if firstByte != secondByte {println("firstByte = \(firstByte) secondByte = \(secondByte)")}
}
}
}
As I expected, there were no differences when I compared the bitmapData from the original bitmap rep to the bitmapData from the bitmap rep created with bitmapImageRepByRetaggingWithColorSpace.
It got more interesting, however when I compared the bitmapData from the original bitmap rep to the data from the bitmap rep created with bitmapImageRepByConvertingToColorSpace.
There were lots of differences in the data. Small differences, but lots of them.
Even though there were no differences I could see in the PNG files, the underlying data had been changed by bitmapImageRepByConvertingToColorSpace.
All that said, I think you should be able to pass .bitmapData from any of these bitmap reps to an OpenGL texture. The data from the bitmap rep created with bitmapImageRepByConvertingToColorSpace might create a texture that looks different, but it should be valid data.

Spritekit Swift particle SKEmitterNode add remove

so this is nice for create a particle, but whats the right way to remove it , after the duration, sparkEmmiter.particleLifetime do not remove it automatically
let sparkEmmiter = SKEmitterNode(fileNamed: "MyParticle.sks")
sparkEmmiter.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2 - 200)
sparkEmmiter.name = "sparkEmmitter"
sparkEmmiter.zPosition = 1
sparkEmmiter.targetNode = self
sparkEmmiter.particleLifetime = 1
self.addChild(sparkEmmiter)
this solutions produce simulator crash
var re = SKAction.waitForDuration(1)
var remove = SKAction.removeFromParent()
var seq = SKAction.sequence([re , remove])
sparkEmmiter.runAction(seq)

Windows Forms chart with two aligned/overlapping areas don't use the entire control

A chart on a form I created has two overlapping areas. The overlapping part works just fine. The problem is that visible graph only takes up half the height of the chart control:
The bottom half of the control is left empty (presumably because that's where the second area would have gone were the two areas not aligned?). I can't figure out how to get the chart to use the entire control. The code is below:
chart1.Dock = DockStyle.Fill;
chart1.Legends.Add(new Legend { Name = "Legend1" });
chart1.Location = new Point(435, 3);
chart1.Name = "chart1";
chart1.Size = new Size(426, 287);
chart1.TabIndex = 2;
chart1.Text = "chart1";
var firstArea = chart1.ChartAreas.Add("First Area");
var seriesFirst = chart1.Series.Add("First Series");
seriesFirst.ChartType = SeriesChartType.Line;
seriesFirst.Points.Add(new DataPoint(10, 55));
seriesFirst.Points.Add(new DataPoint(11, 56));
seriesFirst.Points.Add(new DataPoint(12, 59));
var secondArea = chart1.ChartAreas.Add("Second Area");
secondArea.BackColor = Color.Transparent;
secondArea.AlignmentOrientation = AreaAlignmentOrientations.All;
secondArea.AlignmentStyle = AreaAlignmentStyles.All;
secondArea.AlignWithChartArea = firstArea.Name;
secondArea.AxisY.LabelStyle.Enabled = false;
secondArea.AxisX.LabelStyle.Enabled = false;
var seriesSecond = chart1.Series.Add("Second Series");
seriesSecond.ChartType = SeriesChartType.Line;
seriesSecond.ChartArea = secondArea.Name;
seriesSecond.Points.Add(new DataPoint(10, 1001));
seriesSecond.Points.Add(new DataPoint(11, 1015));
seriesSecond.Points.Add(new DataPoint(12, 1016));
This is some old code I've dug out and modified to suit your example. The problem is the InnerPlotPosition.Auto and Position.Auto status of the ChartAreas, thats why after you add the second chart the first charts auto position jumps up and then the second chart aligns with the new InnerPlotPosition.Auto values.
You can try turning this off but I think its easier to just position the first chart manually and then allow the second to align with the new manual position. It produces the below image (minus your legend you can work the values needed yourself)
Bit of pain in the ass solution but hopefully it helps
Dim chart1 As New Chart
Me.Controls.Add(chart1)
chart1.Location = New Point(435, 3)
chart1.Name = "chart1"
chart1.Size = New Size(426, 287)
chart1.TabIndex = 2
chart1.Text = "chart1"
Dim firstArea As ChartArea = chart1.ChartAreas.Add("First Area")
Dim seriesFirst = chart1.Series.Add("First Series")
seriesFirst.ChartType = SeriesChartType.Line
seriesFirst.Points.Add(New DataPoint(10, 55))
seriesFirst.Points.Add(New DataPoint(11, 56))
seriesFirst.Points.Add(New DataPoint(12, 59))
Dim secondArea As ChartArea = chart1.ChartAreas.Add("Second Area")
secondArea.BackColor = Color.Transparent
secondArea.AlignmentOrientation = AreaAlignmentOrientations.All
secondArea.AlignmentStyle = AreaAlignmentStyles.All
secondArea.AlignWithChartArea = firstArea.Name
secondArea.AxisY.LabelStyle.Enabled = False
secondArea.AxisX.LabelStyle.Enabled = False
Dim seriesSecond = chart1.Series.Add("Second Series")
seriesSecond.ChartType = SeriesChartType.Line
seriesSecond.ChartArea = secondArea.Name
seriesSecond.Points.Add(New DataPoint(10, 1001))
seriesSecond.Points.Add(New DataPoint(11, 1015))
seriesSecond.Points.Add(New DataPoint(12, 1016))
' *** Set locational values here for your first chart***
Dim heightAboveChartArea As Integer = 20
Dim heightBelowChartArea As Integer = 20
Dim axisLabelHeight As Integer = 40
Dim widthLeftOfChartArea As Integer = 20
Dim widthRightOfChartArea As Integer = 20
Dim heightPerBar As Integer = 20
Dim numberOfPoints As Integer = chart1.Series(0).Points.Count
' *** The following code should not normally be modified ***
chart1.Height = heightAboveChartArea + heightBelowChartArea + axisLabelHeight + (numberOfPoints * heightPerBar)
chart1.ChartAreas(0).Position.X = widthLeftOfChartArea / chart1.Width * 100
chart1.ChartAreas(0).Position.Width = 100 - (widthRightOfChartArea / chart1.Width * 100) - chart1.ChartAreas(0).Position.X
chart1.ChartAreas(0).Position.Y = (heightAboveChartArea / chart1.Height * 100)
chart1.ChartAreas(0).Position.Height = 100 - (heightBelowChartArea / chart1.Height * 100) - chart1.ChartAreas(0).Position.Y
I thought about monkeying with the position, but I'd have to take into account borders and the legend and other chart components and assumed I'd never get it as good as the auto-positioning provided by the chart - and it would drive me nuts. However, the suggestion by TylerDurden led me to the idea of simply delaying the addition of the second series/area until after the chart had rendered at least once and had calculated the position. This turned out to be non-trivial, since for most of the chart's initialization the X, Y, Height and Width are still zero. The best way I found was to add the second series in the Form's Shown event:
private void OnShown(object sender, EventArgs eventArgs)
{
Application.DoEvents();
var f = chart1.ChartAreas[0].Position.ToRectangleF();
chart1.ChartAreas[0].Position.Auto = false;
chart1.ChartAreas[0].Position.X = f.X;
chart1.ChartAreas[0].Position.Y = f.Y;
chart1.ChartAreas[0].Position.Height = f.Height;
chart1.ChartAreas[0].Position.Width = f.Width;
// add second area/series here
The call to Application.DoEvents() is required to force the chart to render and calculate the Position. Since Position is a percentage, both chart areas will always occupy the full height and width of the parent Chart.

Resources