I wonder if it's possible to loop over a Photoshop path and set all the points on it to be linear?
Unlike Illustrator, paths in Photoshop is not well documented and a bit cumbersome:
// Switch off any dialog boxes
displayDialogs = DialogModes.ERROR // ERRORS ONLY DialogModes 2
// create a document to work with
var docRef = app.documents.add(200, 200, 72, "untitled");
// call the source document
var srcDoc = app.activeDocument;
// create the array of PathPointInfo objects
var lineArray = new Array();
lineArray.push(new PathPointInfo());
lineArray[0].kind = PointKind.SMOOTHPOINT;
lineArray[0].anchor = new Array(50, 100); // A
lineArray[0].leftDirection = [0, 0];
lineArray[0].rightDirection = lineArray[0].anchor;
lineArray.push(new PathPointInfo());
lineArray[1].kind = PointKind.SMOOTHPOINT;
lineArray[1].anchor = new Array(150, 150); // B
lineArray[1].leftDirection = [0, 0];
lineArray[1].rightDirection = [0, 0];
// create a SubPathInfo object, which holds the line array in its entireSubPath property.
var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;
pathName = "my path";
//create the path item, passing subpath to add method
var myPathItem = docRef.pathItems.add(pathName, lineSubPathArray);
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL
myPath = srcDoc.pathItems.getByName(pathName);
var subPathCount = myPath.subPathItems.length; // Count of subpaths
var msg = "";
msg += subPathCount + " path(s)\n";
for (var i = 0; i < myPath.subPathItems.length; i++)
{
msg += myPath.subPathItems[i] + "\n";
}
alert(msg);
Firstly, I'm having difficulty access the subPathItems items after I created the path.
Secondly, I don't know what the settings for the tangents (.leftDirection, .rightDirection) are for a linear path.
Apart from that it's peachy ;)
Related
I'm trying to iterate over a create path in Photoshop finding out the anchor points position etc
var srcDoc = app.activeDocument;
// create the array of PathPointInfo objects
var lineArray = new Array();
lineArray.push(new PathPointInfo());
lineArray[0].kind = PointKind.CORNERPOINT;
lineArray[0].anchor = new Array(20, 160);
lineArray[0].leftDirection = [35, 200];
lineArray[0].rightDirection = lineArray[0].anchor;
lineArray.push(new PathPointInfo());
lineArray[1].kind = PointKind.CORNERPOINT;
lineArray[1].anchor = new Array(20, 40);
lineArray[1].leftDirection = lineArray[1].anchor;
lineArray[1].rightDirection = [220, 260];
// create a SubPathInfo object, which holds the line array in its entireSubPath property.
var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;
//create the path item, passing subpath to add method
var myPathItem = srcDoc.pathItems.add("A Line", lineSubPathArray);
for (var i = 0; i < lineSubPathArray[0].entireSubPath.length; i++)
{
var b = lineSubPathArray[0].entireSubPath[i].anchor;
alert(b);
}
This works fine, but instead of creating the path and finding out it's information I want to loop over each path and get the same. This should be the same as the loop above only without explicitly calling lineSubPathArray and its parts.
for (var i = 0; i < srcDoc.pathItems[0].subPathItems.pathPoints.length; i++) // wrong I think
{
var b = srcDoc.pathItems[0].entireSubPath[i].anchor; // wrong
alert(b);
}
Almost: you need to iterate through subPathItems which consist of pathPoints:
var srcDoc = activeDocument;
var workPath = srcDoc.pathItems[0];
var i, k, b;
for (i = 0; i < workPath.subPathItems.length; i++) {
for (k = 0; k < workPath.subPathItems[i].pathPoints.length; k++) {
b = workPath.subPathItems[i].pathPoints[k].anchor;
alert(b);
}
}
I have been struggling in taking screenshots with DirectX, the problem is, it's working but seems to be missing some colors (black outline is missing for example), and some stuff that is also rendered by DX doesn't show.
I have uploaded the images (how the image should render and the rendered one) and also the code, what might be the issue?
Correct Image
Rendered Image
Greetings
public class Screenshot
{
public static void TakeScreenshot(string name = null)
{
var t = new Thread((ThreadStart) delegate
{
// destination folder
var destinationFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments, Environment.SpecialFolderOption.Create) + "\\My Software\\Screenshots";
if (!Directory.Exists(destinationFolder)) Directory.CreateDirectory(destinationFolder);
// file name
string filename = name;
if (string.IsNullOrEmpty(name))
filename = "image-" + (Directory.GetFiles(destinationFolder, "*.png").Count() + 1).ToString("000") + ".png";
// # of graphics card adapter
const int numAdapter = 0;
// # of output device (i.e. monitor)
const int numOutput = 0;
// Create DXGI Factory1
var factory = new Factory1();
var adapter = factory.GetAdapter1(numAdapter);
// Create device from Adapter
var device = new Device(adapter);
// Get DXGI.Output
var output = adapter.GetOutput(numOutput);
var output1 = output.QueryInterface<Output1>();
// Width/Height of desktop to capture
int width = ((SharpDX.Rectangle)output.Description.DesktopBounds).Width;
int height = ((SharpDX.Rectangle)output.Description.DesktopBounds).Height;
// Create Staging texture CPU-accessible
var textureDesc = new Texture2DDescription
{
CpuAccessFlags = CpuAccessFlags.Read,
BindFlags = BindFlags.None,
Format = Format.B8G8R8A8_UNorm,
Width = width,
Height = height,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = ResourceUsage.Staging
};
var screenTexture = new Texture2D(device, textureDesc);
// Duplicate the output
var duplicatedOutput = output1.DuplicateOutput(device);
bool captureDone = false;
for (int i = 0; !captureDone; i++)
{
try
{
SharpDX.DXGI.Resource screenResource;
OutputDuplicateFrameInformation duplicateFrameInformation;
// Try to get duplicated frame within given time
duplicatedOutput.AcquireNextFrame(10000, out duplicateFrameInformation, out screenResource);
if (i > 0)
{
// copy resource into memory that can be accessed by the CPU
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
device.ImmediateContext.CopyResource(screenTexture2D, screenTexture);
// Get the desktop capture texture
var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None);
// Create Drawing.Bitmap
var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
var boundsRect = new System.Drawing.Rectangle(0, 0, width, height);
// Copy pixels from screen capture Texture to GDI bitmap
var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
var sourcePtr = mapSource.DataPointer;
var destPtr = mapDest.Scan0;
for (int y = 0; y < height; y++)
{
// Copy a single line
Utilities.CopyMemory(destPtr, sourcePtr, width * 4);
// Advance pointers
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
destPtr = IntPtr.Add(destPtr, mapDest.Stride);
}
// Release source and dest locks
bitmap.UnlockBits(mapDest);
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
// Save the output
bitmap.Save(destinationFolder + Path.DirectorySeparatorChar + filename);
// Send Message
Main.Chat.AddMessage(null, "~b~Screenshot saved as " + filename);
// Capture done
captureDone = true;
}
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
}
catch (SharpDXException e)
{
if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
{
throw e;
}
}
}
});
t.IsBackground = true;
t.Start();
}
}
As you can see here http://allopensensors.com/profile/andreas/
the date on x-axis is nonreadable. I'd like to add a line break. How can i solve this?
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.pathToImages = "http://allopensensors.com/amcharts/images/";
chart.dataProvider = chartData;
chart.marginLeft = 10;
chart.categoryField = "year";
chart.dataDateFormat = "YYYY-MM-DD JJ:NN:SS";
// listen for "dataUpdated" event (fired when chart is inited) and call zoomChart method when it happens
chart.addListener("dataUpdated", zoomChart);
// AXES
// category
var categoryAxis = chart.categoryAxis;
// categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
categoryAxis.minPeriod = "200"; // our data is yearly, so we set minPeriod to YYYY
categoryAxis.dashLength = 3;
categoryAxis.minorGridEnabled = true;
categoryAxis.minorGridAlpha = 0.1;
// value
var valueAxis = new AmCharts.ValueAxis();
valueAxis.axisAlpha = 0;
valueAxis.inside = true;
valueAxis.dashLength = 3;
chart.addValueAxis(valueAxis);
// GRAPH
graph = new AmCharts.AmGraph();
graph.type = "smoothedLine"; // this line makes the graph smoothed line.
graph.lineColor = "#d1655d";
graph.negativeLineColor = "#637bb6"; // this line makes the graph to change color when it drops below 0
graph.bullet = "round";
graph.bulletSize = 8;
graph.bulletBorderColor = "#FFFFFF";
graph.bulletBorderAlpha = 1;
graph.bulletBorderThickness = 2;
graph.lineThickness = 2;
graph.valueField = "value";
graph.balloonText = "[[category]]<br><b><span style='font-size:14px;'>[[value]]</span></b>";
chart.addGraph(graph);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chartCursor.cursorAlpha = 0;
chartCursor.cursorPosition = "mouse";
chartCursor.categoryBalloonDateFormat = "JJ:NN:SS";
chart.addChartCursor(chartCursor);
// SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);
chart.creditsPosition = "bottom-right";
// WRITE
chart.write("chartdiv");
});
// this method is called when chart is first inited as we listen for "dataUpdated" event
function zoomChart() {
// different zoom methods can be used - zoomToIndexes, zoomToDates, zoomToCategoryValues
// chart.zoomToDates(new Date(1972, 0), new Date(2200, 0));
chart.zoomToIndexes(chartData.length - 40, chartData.length - 1);
}
To make it readable, you can rotate the labels with custom angle. Try categoryAxis.labelRotation : 45
For Reference: http://www.amcharts.com/demos/column-with-rotated-series/
Hope it helps!
It's tedious to have to click to "Save for web" and change the resolution each time I want to create the image as a different resolution. Is there a way to write a script to automatically achieve this, for multiple resolutions as one?
For that i myself use this function
function saveDocumentAsPng(d, width, height) {
var fileName = d.fullName.toString();
if(fileName.lastIndexOf(".") >= 0) { fileName = fileName.substr(0, fileName.lastIndexOf("."));}
fileName += "_wxh.png".replace("w", width).replace("h", height);
var exportOptions = new ExportOptionsPNG24();
exportOptions.horizontalScale = exportOptions.verticalScale = 100 * Math.max(width/d.width, height/d.height);
var file = new File(fileName);
app.activeDocument = d;
d.exportFile(file, ExportType.PNG24, exportOptions);
}
Note that it names a resulting png's with “_[width]x[height]” suffix.
I wrote my function based on a sample from adobe's javascript reference http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/illustrator/scripting/illustrator_scripting_reference_javascript_cs5.pdf (page 59).
This is an old post, but it inspired me to create a different version for my Android project that I'd like to share.
Just create a 144x144 pixels document and run this:
var doc = app.activeDocument;
// This is the scale factor that you can see in "Percent" textbox of
// the "Save for Web..." dialog box while changing the size of the image
var scale = [100, 66.67, 50, 33.33]
// This is the image size for the PNGs files names
var size = [144, 96, 72, 48]
for(var i = 0; i<4; i++)
{
var fileName = doc.fullName.toString();
if (fileName.lastIndexOf(".") >= 0) {
// Get the file name without the extension
fileName = fileName.substr(0, fileName.lastIndexOf("."));
}
// Name each file with yours size to avoid overwrite
fileName += "_wxh.png".replace("w", size[i]).replace("h", size[i]);
var exportOptions = new ExportOptionsPNG24();
exportOptions.horizontalScale = exportOptions.verticalScale = scale[i];
exportOptions.artBoardClipping = true;
var file = new File(fileName);
doc.exportFile(file, ExportType.PNG24, exportOptions);
}
Window.alert ("Successfully exported!", "Success");
Thank you!
Here is the script that will export all files of the selected folder into PNG. You can specify resolution in this code and image quality will be good. In this code by default resolution is 600
var folder = Folder.selectDialog();
if (folder) {
var files = folder.getFiles("*.ai");
for (var i = 0; i < files.length; i++) {
var currentFile = files[i];
app.open(currentFile);
var activeDocument = app.activeDocument;
var pngFolder = Folder(currentFile.path + "/PNG");
if (!pngFolder.exists)
pngFolder.create();
var fileName = activeDocument.name.split('.')[0] + ".png";
var destinationFile = File(pngFolder + "/" + fileName);
// Export Artboard where you can set resolution for an image. Set to 600 by default in code.
var opts = new ImageCaptureOptions();
opts.resolution = 600;
opts.antiAliasing = true;
opts.transparency = true;
try {
activeDocument.imageCapture(new File(destinationFile), activeDocument.geometricBounds, opts);
} catch (e) {
}
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
currentFile = null;
}
}
If you want to export in jpg format, just change extension of the file in the code in the following line
var fileName = activeDocument.name.split('.')[0] + ".png";
change to
var fileName = activeDocument.name.split('.')[0] + ".jpg"; // For jpg
Also, you can change the name of the file and where the exported file will be stored according to your requirement.
Hope my answer will help you.
I'm using ExtendScript for scripting Adobe Illustrator. I was wondering if there was a sneaky way or a script available to programmatically capture and then replicate a path shape, sort of JavaScript's .toSource() equivalent.
Thanks
Try this:
main();
function main(){
var doc = app.activeDocument; // get the active doc
var coords = new Array(); // make a new array for the coords of the path
var directions = new Array();
var sel = doc.selection[0];// get first object in selection
if(sel == null) {
// check if something is slected
alert ("You need to sevlect a path");
return;
}
var points = sel.pathPoints;// isolate pathpoints
// loop points
for (var i = 0; i < points.length; i++) {
// this could be done in one lines
// just to see whats going on line like
//~ coords.push(new Array(points[i].anchor[0],points[i].anchor[1]));
var p = points[i]; // the point
var a = p.anchor; // his anchor
var px = a[0];// x
var py = a[1]; // y
var ldir = p.leftDirection;
var rdir = p.rightDirection;
directions.push(new Array(ldir,rdir));
coords.push(new Array(px,py));// push into new array of array
}
var new_path = doc.pathItems.add(); // add a new pathitem
new_path.setEntirePath(coords);// now build the path
// check if path was closed
if(sel.closed){
new_path.closed = true;
}
// set the left and right directions
for(var j = 0; j < new_path.pathPoints.length;j++){
new_path.pathPoints[j].leftDirection = directions[j][0];
new_path.pathPoints[j].rightDirection = directions[j][1];
}
}