github.com/boki/go-xmp@v1.0.1/models/ps/model.go (about) 1 // Copyright (c) 2017-2018 Alexander Eichhorn 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 // see also Photoshop Specification at 16 // http://www.adobe.com/devnet-apps/photoshop/fileformatashtml 17 18 // Package ps implements Adobe Photoshop metadata as defined by XMP Specification Part 2 Chapter 3.2. 19 package ps 20 21 import ( 22 "fmt" 23 "trimmer.io/go-xmp/xmp" 24 ) 25 26 var ( 27 NsPhotoshop = xmp.NewNamespace("photoshop", "http://ns.adobe.com/photoshop/1.0/", NewModel) 28 ) 29 30 func init() { 31 xmp.Register(NsPhotoshop, xmp.ImageMetadata) 32 } 33 34 func NewModel(name string) xmp.Model { 35 return &PhotoshopInfo{} 36 } 37 38 func MakeModel(d *xmp.Document) (*PhotoshopInfo, error) { 39 m, err := d.MakeModel(NsPhotoshop) 40 if err != nil { 41 return nil, err 42 } 43 x, _ := m.(*PhotoshopInfo) 44 return x, nil 45 } 46 47 func FindModel(d *xmp.Document) *PhotoshopInfo { 48 if m := d.FindModel(NsPhotoshop); m != nil { 49 return m.(*PhotoshopInfo) 50 } 51 return nil 52 } 53 54 type PhotoshopInfo struct { 55 AuthorsPosition string `xmp:"photoshop:AuthorsPosition"` 56 CaptionWriter string `xmp:"photoshop:CaptionWriter"` 57 Category string `xmp:"photoshop:Category"` 58 City string `xmp:"photoshop:City"` 59 ColorMode ColorMode `xmp:"photoshop:ColorMode"` 60 Country string `xmp:"photoshop:Country"` 61 Credit string `xmp:"photoshop:Credit"` 62 DateCreated xmp.Date `xmp:"photoshop:DateCreated"` 63 DocumentAncestors AnchestorArray `xmp:"photoshop:DocumentAncestors"` 64 Headline string `xmp:"photoshop:Headline"` 65 History string `xmp:"photoshop:History"` 66 ICCProfile string `xmp:"photoshop:ICCProfile"` 67 Instructions string `xmp:"photoshop:Instructions"` 68 Layer *Layer `xmp:"photoshop:Layer"` 69 SidecarForExtension string `xmp:"photoshop:SidecarForExtension"` // "NEF" 70 Source string `xmp:"photoshop:Source"` 71 State string `xmp:"photoshop:State"` 72 SupplementalCategories xmp.StringArray `xmp:"photoshop:SupplementalCategories"` 73 TextLayers LayerList `xmp:"photoshop:TextLayers"` 74 TransmissionReference string `xmp:"photoshop:TransmissionReference"` 75 Urgency int `xmp:"photoshop:Urgency"` // 1 - 8 76 77 EmbeddedXMPDigest string `xmp:"photoshop:EmbeddedXMPDigest,omit"` // "00000000000000000000000000000000" 78 LegacyIPTCDigest string `xmp:"photoshop:LegacyIPTCDigest,omit"` // "AA5133A9479EA0F732E6A7414060A81F" 79 } 80 81 func (x PhotoshopInfo) Can(nsName string) bool { 82 return NsPhotoshop.GetName() == nsName 83 } 84 85 func (x PhotoshopInfo) Namespaces() xmp.NamespaceList { 86 return xmp.NamespaceList{NsPhotoshop} 87 } 88 89 func (x *PhotoshopInfo) SyncModel(d *xmp.Document) error { 90 return nil 91 } 92 93 func (x *PhotoshopInfo) SyncFromXMP(d *xmp.Document) error { 94 return nil 95 } 96 97 func (x PhotoshopInfo) SyncToXMP(d *xmp.Document) error { 98 return nil 99 } 100 101 func (x *PhotoshopInfo) CanTag(tag string) bool { 102 _, err := xmp.GetNativeField(x, tag) 103 return err == nil 104 } 105 106 func (x *PhotoshopInfo) GetTag(tag string) (string, error) { 107 if v, err := xmp.GetNativeField(x, tag); err != nil { 108 return "", fmt.Errorf("%s: %v", NsPhotoshop.GetName(), err) 109 } else { 110 return v, nil 111 } 112 } 113 114 func (x *PhotoshopInfo) SetTag(tag, value string) error { 115 if err := xmp.SetNativeField(x, tag, value); err != nil { 116 return fmt.Errorf("%s: %v", NsPhotoshop.GetName(), err) 117 } 118 return nil 119 } 120 121 // 3.2.1.1 Ancestor 122 type Anchestor struct { 123 AncestorID xmp.Uri `xmp:"photoshop:AncestorID"` 124 } 125 126 type AnchestorArray []Anchestor 127 128 func (x AnchestorArray) Typ() xmp.ArrayType { 129 return xmp.ArrayTypeUnordered 130 } 131 132 func (x AnchestorArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 133 return xmp.MarshalArray(e, node, x.Typ(), x) 134 } 135 136 func (x *AnchestorArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 137 return xmp.UnmarshalArray(d, node, x.Typ(), x) 138 } 139 140 // 3.2.1.2 Layer 141 type Layer struct { 142 LayerName string `xmp:"photoshop:LayerName"` 143 LayerText string `xmp:"photoshop:LayerText"` 144 } 145 146 func (x Layer) IsZero() bool { 147 return x.LayerName == "" && x.LayerText == "" 148 } 149 150 type LayerList []Layer 151 152 func (x LayerList) Typ() xmp.ArrayType { 153 return xmp.ArrayTypeOrdered 154 } 155 156 func (x LayerList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 157 return xmp.MarshalArray(e, node, x.Typ(), x) 158 } 159 160 func (x *LayerList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 161 return xmp.UnmarshalArray(d, node, x.Typ(), x) 162 } 163 164 type ColorMode int 165 166 const ( 167 ColorModeBitmap = 0 // 0 = Bitmap 168 ColorModeGrayscale = 1 // 1 = Gray scale 169 ColorModeIndexed = 2 // 2 = Indexed colour 170 ColorModeRGB = 3 // 3 = RGB colour 171 ColorModeCMYK = 4 // 4 = CMYK colour 172 ColorModeMultiChannel = 7 // 7 = Multi-channel 173 ColorModeDuotone = 8 // 8 = Duotone 174 ColorModeLAB = 9 // 9 = LAB colour 175 )