mirror of
https://github.com/sbrow/ps.git
synced 2025-12-29 18:47:38 -05:00
gitflow-hotfix-stash: v1.0
This commit is contained in:
@@ -14,7 +14,7 @@ type Color interface {
|
|||||||
Hex() []uint8 // The color in hexadecimal format.
|
Hex() []uint8 // The color in hexadecimal format.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare determines which of two colors is "brighter".
|
// Compare returns the brighter of a and b.
|
||||||
func Compare(a, b Color) Color {
|
func Compare(a, b Color) Color {
|
||||||
A := a.RGB()
|
A := a.RGB()
|
||||||
B := b.RGB()
|
B := b.RGB()
|
||||||
@@ -26,7 +26,7 @@ func Compare(a, b Color) Color {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// RGB is a color in RGB format. It implements the Color interface.
|
// RGB is a color format. It implements the Color interface.
|
||||||
type RGB struct {
|
type RGB struct {
|
||||||
Red int
|
Red int
|
||||||
Green int
|
Green int
|
||||||
@@ -38,9 +38,10 @@ func (r RGB) RGB() [3]int {
|
|||||||
return [3]int{r.Red, r.Green, r.Blue}
|
return [3]int{r.Red, r.Green, r.Blue}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement RGB.Hex()
|
|
||||||
func (r RGB) Hex() []uint8 {
|
func (r RGB) Hex() []uint8 {
|
||||||
return make([]uint8, 6)
|
src := []byte([]uint8{uint8(r.Red), uint8(r.Green), uint8(r.Blue)})
|
||||||
|
hex := make([]byte, hex.EncodedLen(len(src)))
|
||||||
|
return []uint8(hex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hex is a color in hexadecimal format. It implements the Color interface.
|
// Hex is a color in hexadecimal format. It implements the Color interface.
|
||||||
|
|||||||
10
examples_test.go
Normal file
10
examples_test.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package ps
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func ExampleJSLayer() {
|
||||||
|
// The path of a layer inside a top level group.
|
||||||
|
path := "/Group 1/Layer 1"
|
||||||
|
fmt.Println(JSLayer(path))
|
||||||
|
// Output: app.activeDocument.layerSets.getByName('Group 1').artLayers.getByName('Layer 1');
|
||||||
|
}
|
||||||
129
ps.go
129
ps.go
@@ -2,6 +2,8 @@
|
|||||||
// The interaction between the two is implemented using Javascript/VBScript.
|
// The interaction between the two is implemented using Javascript/VBScript.
|
||||||
//
|
//
|
||||||
// Currently only supports Photoshop CS5 Windows x86_64.
|
// Currently only supports Photoshop CS5 Windows x86_64.
|
||||||
|
//
|
||||||
|
// TODO: Creatue a Photoshop struct to hold program values and functions.
|
||||||
package ps
|
package ps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -9,12 +11,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
// "log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
// "update"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The name of the program that runs scripts on this OS.
|
// The name of the program that runs scripts on this OS.
|
||||||
@@ -34,11 +36,16 @@ func init() {
|
|||||||
case "darwin":
|
case "darwin":
|
||||||
scmd = "osacript"
|
scmd = "osacript"
|
||||||
}
|
}
|
||||||
|
// update.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start opens Photoshop.
|
// ApplyDataset fills out a template file with information
|
||||||
func Start() error {
|
// from a given dataset (csv) file. It is important to note that running this
|
||||||
_, err := run("start")
|
// function will change data in the Photoshop document, but will not update
|
||||||
|
// data in the Go Document struct- you will have to implement syncing
|
||||||
|
// them yourself.
|
||||||
|
func ApplyDataset(name string) error {
|
||||||
|
_, err := DoJs("applyDataset.jsx", name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,28 +55,14 @@ func Close(save PSSaveOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens a Photoshop document with the specified path.
|
// DoAction runs the Photoshop Action "name" from the Action Set "set".
|
||||||
// If Photoshop is not currently running, it is started before
|
func DoAction(set, name string) error {
|
||||||
// opening the document.
|
_, err := run("action", set, name)
|
||||||
func Open(path string) error {
|
|
||||||
_, err := run("open", path)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quit exits Photoshop with the given saving option.
|
|
||||||
func Quit(save PSSaveOptions) error {
|
|
||||||
_, err := run("quit", save.String())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SaveAs saves the Photoshop document to the given location.
|
|
||||||
func SaveAs(path string) error {
|
|
||||||
_, err := run("save", path)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoJs runs a Photoshop Javascript script file (.jsx) from the specified location.
|
// DoJs runs a Photoshop Javascript script file (.jsx) from the specified location.
|
||||||
// It can't directly return output, so instead the script must write their output to
|
// The script can't directly return output, so instead it writes output to
|
||||||
// a temporary file ($TEMP/js_out.txt), whose contents is then read and returned.
|
// a temporary file ($TEMP/js_out.txt), whose contents is then read and returned.
|
||||||
func DoJs(path string, args ...string) (out []byte, err error) {
|
func DoJs(path string, args ...string) (out []byte, err error) {
|
||||||
// Temp file for js to output to.
|
// Temp file for js to output to.
|
||||||
@@ -97,16 +90,43 @@ func DoJs(path string, args ...string) (out []byte, err error) {
|
|||||||
return cmd, err
|
return cmd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait prints a message to the console and halts operation until the user
|
// JSLayer "compiles" Javascript code to get an ArtLayer with the given path.
|
||||||
// signals that they are ready (by pushing enter).
|
// The output always ends with a semicolon, so if you want to access a specific
|
||||||
|
// property of the layer, you'll have to trim the output before concatenating.
|
||||||
//
|
//
|
||||||
// Useful for when you need to do something by hand in the middle of an
|
// TODO: get rid of the semicolon.
|
||||||
// otherwise automated process. (i.e. loading a dataset).
|
func JSLayer(path string, art ...bool) string {
|
||||||
func Wait(msg string) {
|
path = strings.TrimLeft(path, "/")
|
||||||
fmt.Print(msg)
|
pth := strings.Split(path, "/")
|
||||||
var input string
|
js := "app.activeDocument"
|
||||||
fmt.Scanln(&input)
|
last := len(pth) - 1
|
||||||
fmt.Println()
|
if len(art) > 0 {
|
||||||
|
pth = pth[:len(pth)-1]
|
||||||
|
last--
|
||||||
|
}
|
||||||
|
if last > 0 {
|
||||||
|
for i := 0; i < last; i++ {
|
||||||
|
js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pth[last] != "" {
|
||||||
|
js += fmt.Sprintf(".artLayers.getByName('%s')", pth[last])
|
||||||
|
}
|
||||||
|
return js + ";"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens a Photoshop document with the specified path.
|
||||||
|
// If Photoshop is not currently running, it is started before
|
||||||
|
// opening the document.
|
||||||
|
func Open(path string) error {
|
||||||
|
_, err := run("open", path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quit exits Photoshop using the given save option.
|
||||||
|
func Quit(save PSSaveOptions) error {
|
||||||
|
_, err := run("quit", save.String())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// run handles running the script files, returning output, and displaying errors.
|
// run handles running the script files, returning output, and displaying errors.
|
||||||
@@ -143,43 +163,26 @@ func run(name string, args ...string) ([]byte, error) {
|
|||||||
return out.Bytes(), nil
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoAction runs the Photoshop Action "name" from the Action Set "set".
|
// SaveAs saves the Photoshop document to the given location.
|
||||||
func DoAction(set, name string) error {
|
func SaveAs(path string) error {
|
||||||
_, err := run("action", set, name)
|
_, err := run("save", path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyDataset fills out a template file with information
|
// Start opens Photoshop.
|
||||||
// from a given dataset (csv) file. It is important to note that running this
|
func Start() error {
|
||||||
// function will change data in the Photoshop document, but will not update
|
_, err := run("start")
|
||||||
// data in the Go Document struct- you will have to implement syncing
|
|
||||||
// them yourself.
|
|
||||||
func ApplyDataset(name string) error {
|
|
||||||
_, err := DoJs("applyDataset.jsx", name)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSLayer "compiles" Javascript code to get an ArtLayer with the given path.
|
// Wait prints a message to the console and halts operation until the user
|
||||||
// The output always ends with a semicolon, so if you want to access a specific
|
// signals that they are ready to continue (by pushing enter).
|
||||||
// property of the layer, you'll have to trim the output before concatenating.
|
|
||||||
//
|
//
|
||||||
// TODO: get rid of the semicolon.
|
// Useful for when you need to do something by hand in the middle of an
|
||||||
func JSLayer(path string, art ...bool) string {
|
// otherwise automated process. (i.e. importing a dataset).
|
||||||
path = strings.TrimLeft(path, "/")
|
func Wait(msg string) {
|
||||||
pth := strings.Split(path, "/")
|
fmt.Print(msg)
|
||||||
js := "app.activeDocument"
|
var input string
|
||||||
last := len(pth) - 1
|
fmt.Scanln(&input)
|
||||||
if len(art) > 0 {
|
fmt.Println()
|
||||||
pth = pth[:len(pth)-1]
|
|
||||||
last--
|
|
||||||
}
|
|
||||||
if last > 0 {
|
|
||||||
for i := 0; i < last; i++ {
|
|
||||||
js += fmt.Sprintf(".layerSets.getByName('%s')", pth[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pth[last] != "" {
|
|
||||||
js += fmt.Sprintf(".artLayers.getByName('%s')", pth[last])
|
|
||||||
}
|
|
||||||
return js + ";"
|
|
||||||
}
|
}
|
||||||
|
|||||||
32
ps_test.go
32
ps_test.go
@@ -1,3 +1,4 @@
|
|||||||
|
// TODO: Update package tests.
|
||||||
package ps
|
package ps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -248,6 +249,37 @@ func TestDoJs_HideLayer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTextItem(t *testing.T) {
|
||||||
|
// err := Open("F:\\GitLab\\dreamkeepers-psd\\Template009.1.psd")
|
||||||
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
d, err := ActiveDocument()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, lyr := range d.ArtLayers() {
|
||||||
|
if lyr.Name() == "Text" {
|
||||||
|
lyr.SetText("Butts")
|
||||||
|
// lyr.FmtText(0, 5, "Arial", "Regular")
|
||||||
|
// lyr.FmtText(0, 3, "Arial", "Bold")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* byt := []byte(`{"Name": "lyr", "TextItem": {"Contents": "lyr", "Size": 12.000, "Font": "ArialItalic"}}`)
|
||||||
|
lyr := &ArtLayer{}
|
||||||
|
// byt := []byte(`{"Name": "lyr"}`)
|
||||||
|
// lyr := &TextItem{}
|
||||||
|
err := lyr.UnmarshalJSON(byt)
|
||||||
|
fmt.Printf("%+v\n", lyr)
|
||||||
|
fmt.Println(lyr.TextItem)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkDoc_Go(b *testing.B) {
|
func BenchmarkDoc_Go(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := ActiveDocument()
|
_, err := ActiveDocument()
|
||||||
|
|||||||
36
structs.go
36
structs.go
@@ -72,6 +72,10 @@ func (d *Document) Name() string {
|
|||||||
return d.name
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Document) Parent() Group {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// The height of the document, in pixels.
|
// The height of the document, in pixels.
|
||||||
func (d *Document) Height() int {
|
func (d *Document) Height() int {
|
||||||
return d.height
|
return d.height
|
||||||
@@ -100,9 +104,6 @@ func (d *Document) LayerSet(name string) *LayerSet {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) Parent() Group {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (d *Document) SetParent(g Group) {}
|
func (d *Document) SetParent(g Group) {}
|
||||||
|
|
||||||
func (d *Document) Path() string {
|
func (d *Document) Path() string {
|
||||||
@@ -178,21 +179,21 @@ func (d *Document) Dump() {
|
|||||||
f.Write(byt)
|
f.Write(byt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArtLayer reflects certain values from an Art Layer in a Photoshop document.
|
// ArtLayer reflects some values from an Art Layer in a Photoshop document.
|
||||||
//
|
//
|
||||||
// TODO: Make TextLayer a subclass of ArtLayer.
|
// TODO: Make TextLayer a subclass of ArtLayer.
|
||||||
type ArtLayer struct {
|
type ArtLayer struct {
|
||||||
name string // The layer's name.
|
name string // The layer's name.
|
||||||
Text *string // The contents of a text layer.
|
bounds [2][2]int // The corners of the layer's bounding box.
|
||||||
bounds [2][2]int // The layers' corners.
|
parent Group // The LayerSet/Document this layer is in.
|
||||||
parent Group // The LayerSet/Document this layer is in.
|
visible bool // Whether or not the layer is visible.
|
||||||
visible bool // Whether or not the layer is visible.
|
current bool // Whether we've checked this layer since we loaded from disk.
|
||||||
current bool // Whether we've checked this layer since we loaded from disk.
|
Color // The layer's color overlay effect (if any).
|
||||||
Color // The layer's color overlay.
|
*Stroke // The layer's stroke effect (if any).
|
||||||
*Stroke // The layer's stroke.
|
*TextItem // The layer's text, if it's a text layer.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bounds returns the furthest corners of the ArtLayer.
|
// Bounds returns the coordinates of the corners of the ArtLayer's bounding box.
|
||||||
func (a *ArtLayer) Bounds() [2][2]int {
|
func (a *ArtLayer) Bounds() [2][2]int {
|
||||||
return a.bounds
|
return a.bounds
|
||||||
}
|
}
|
||||||
@@ -257,6 +258,11 @@ func (a *ArtLayer) Name() string {
|
|||||||
return a.name
|
return a.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parent returns the Document or LayerSet this layer is contained in.
|
||||||
|
func (a *ArtLayer) Parent() Group {
|
||||||
|
return a.parent
|
||||||
|
}
|
||||||
|
|
||||||
// X1 returns the layer's leftmost x value.
|
// X1 returns the layer's leftmost x value.
|
||||||
func (a *ArtLayer) X1() int {
|
func (a *ArtLayer) X1() int {
|
||||||
return a.bounds[0][0]
|
return a.bounds[0][0]
|
||||||
@@ -363,10 +369,6 @@ func (a *ArtLayer) SetStroke(stk Stroke, fill Color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtLayer) Parent() Group {
|
|
||||||
return a.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ArtLayer) Path() string {
|
func (a *ArtLayer) Path() string {
|
||||||
return fmt.Sprintf("%s%s", a.parent.Path(), a.name)
|
return fmt.Sprintf("%s%s", a.parent.Path(), a.name)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user