* Add psd preview support

* Adding required vendor files

* Adding oov/psd license to NOTICE.txt file

* Adding the license notice for gopherjs to the NOTICE.txt

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Jesús Espino
2020-07-31 14:46:22 +02:00
коммит произвёл GitHub
родитель 390cade7fe
Коммит ce82ff7e2b
22 изменённых файлов: 3166 добавлений и 0 удалений

Просмотреть файл

@@ -4132,3 +4132,76 @@ A caching, resizing image proxy written in Go
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
---
## oov/psd
This product contains 'psd' by oov.
A PSD/PSB file reader for go
* HOMEPAGE:
* https://github.com/oov/psd
* LICENSE: MIT
MIT License
Copyright (c) 2016 oov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
## gopherjs
This product contains 'gopherjs' by Richard Musiol.
A Go code to javascript code compiler.
* HOMEPAGE:
* https://github.com/gopherjs/gopherjs
* LICENSE:
Copyright (c) 2013 Richard Musiol. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@@ -24,6 +24,7 @@ import (
"time"
"github.com/disintegration/imaging"
_ "github.com/oov/psd"
"github.com/rwcarlsen/goexif/exif"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"

1
go.mod
Просмотреть файл

@@ -79,6 +79,7 @@ require (
github.com/olivere/elastic v6.2.33+incompatible // indirect
github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.9.0 // indirect
github.com/oov/psd v0.0.0-20200705094106-99303fb2511f
github.com/opentracing/opentracing-go v1.1.0
github.com/pborman/uuid v1.2.0
github.com/pelletier/go-toml v1.8.0 // indirect

2
go.sum
Просмотреть файл

@@ -529,6 +529,8 @@ github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/oov/psd v0.0.0-20200705094106-99303fb2511f h1:slBBh1GLx3xo0xx0v4HT0pI02+UcOJXTYRlg6QtN60Y=
github.com/oov/psd v0.0.0-20200705094106-99303fb2511f/go.mod h1:GHI1bnmAcbp96z6LNfBJvtrjxhaXGkbsk967utPlvL8=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=

24
vendor/github.com/gopherjs/gopherjs/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,24 @@
Copyright (c) 2013 Richard Musiol. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

168
vendor/github.com/gopherjs/gopherjs/js/js.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,168 @@
// Package js provides functions for interacting with native JavaScript APIs. Calls to these functions are treated specially by GopherJS and translated directly to their corresponding JavaScript syntax.
//
// Use MakeWrapper to expose methods to JavaScript. When passing values directly, the following type conversions are performed:
//
// | Go type | JavaScript type | Conversions back to interface{} |
// | --------------------- | --------------------- | ------------------------------- |
// | bool | Boolean | bool |
// | integers and floats | Number | float64 |
// | string | String | string |
// | []int8 | Int8Array | []int8 |
// | []int16 | Int16Array | []int16 |
// | []int32, []int | Int32Array | []int |
// | []uint8 | Uint8Array | []uint8 |
// | []uint16 | Uint16Array | []uint16 |
// | []uint32, []uint | Uint32Array | []uint |
// | []float32 | Float32Array | []float32 |
// | []float64 | Float64Array | []float64 |
// | all other slices | Array | []interface{} |
// | arrays | see slice type | see slice type |
// | functions | Function | func(...interface{}) *js.Object |
// | time.Time | Date | time.Time |
// | - | instanceof Node | *js.Object |
// | maps, structs | instanceof Object | map[string]interface{} |
//
// Additionally, for a struct containing a *js.Object field, only the content of the field will be passed to JavaScript and vice versa.
package js
// Object is a container for a native JavaScript object. Calls to its methods are treated specially by GopherJS and translated directly to their JavaScript syntax. A nil pointer to Object is equal to JavaScript's "null". Object can not be used as a map key.
type Object struct{ object *Object }
// Get returns the object's property with the given key.
func (o *Object) Get(key string) *Object { return o.object.Get(key) }
// Set assigns the value to the object's property with the given key.
func (o *Object) Set(key string, value interface{}) { o.object.Set(key, value) }
// Delete removes the object's property with the given key.
func (o *Object) Delete(key string) { o.object.Delete(key) }
// Length returns the object's "length" property, converted to int.
func (o *Object) Length() int { return o.object.Length() }
// Index returns the i'th element of an array.
func (o *Object) Index(i int) *Object { return o.object.Index(i) }
// SetIndex sets the i'th element of an array.
func (o *Object) SetIndex(i int, value interface{}) { o.object.SetIndex(i, value) }
// Call calls the object's method with the given name.
func (o *Object) Call(name string, args ...interface{}) *Object { return o.object.Call(name, args...) }
// Invoke calls the object itself. This will fail if it is not a function.
func (o *Object) Invoke(args ...interface{}) *Object { return o.object.Invoke(args...) }
// New creates a new instance of this type object. This will fail if it not a function (constructor).
func (o *Object) New(args ...interface{}) *Object { return o.object.New(args...) }
// Bool returns the object converted to bool according to JavaScript type conversions.
func (o *Object) Bool() bool { return o.object.Bool() }
// String returns the object converted to string according to JavaScript type conversions.
func (o *Object) String() string { return o.object.String() }
// Int returns the object converted to int according to JavaScript type conversions (parseInt).
func (o *Object) Int() int { return o.object.Int() }
// Int64 returns the object converted to int64 according to JavaScript type conversions (parseInt).
func (o *Object) Int64() int64 { return o.object.Int64() }
// Uint64 returns the object converted to uint64 according to JavaScript type conversions (parseInt).
func (o *Object) Uint64() uint64 { return o.object.Uint64() }
// Float returns the object converted to float64 according to JavaScript type conversions (parseFloat).
func (o *Object) Float() float64 { return o.object.Float() }
// Interface returns the object converted to interface{}. See table in package comment for details.
func (o *Object) Interface() interface{} { return o.object.Interface() }
// Unsafe returns the object as an uintptr, which can be converted via unsafe.Pointer. Not intended for public use.
func (o *Object) Unsafe() uintptr { return o.object.Unsafe() }
// Error encapsulates JavaScript errors. Those are turned into a Go panic and may be recovered, giving an *Error that holds the JavaScript error object.
type Error struct {
*Object
}
// Error returns the message of the encapsulated JavaScript error object.
func (err *Error) Error() string {
return "JavaScript error: " + err.Get("message").String()
}
// Stack returns the stack property of the encapsulated JavaScript error object.
func (err *Error) Stack() string {
return err.Get("stack").String()
}
// Global gives JavaScript's global object ("window" for browsers and "GLOBAL" for Node.js).
var Global *Object
// Module gives the value of the "module" variable set by Node.js. Hint: Set a module export with 'js.Module.Get("exports").Set("exportName", ...)'.
var Module *Object
// Undefined gives the JavaScript value "undefined".
var Undefined *Object
// Debugger gets compiled to JavaScript's "debugger;" statement.
func Debugger() {}
// InternalObject returns the internal JavaScript object that represents i. Not intended for public use.
func InternalObject(i interface{}) *Object {
return nil
}
// MakeFunc wraps a function and gives access to the values of JavaScript's "this" and "arguments" keywords.
func MakeFunc(fn func(this *Object, arguments []*Object) interface{}) *Object {
return Global.Call("$makeFunc", InternalObject(fn))
}
// Keys returns the keys of the given JavaScript object.
func Keys(o *Object) []string {
if o == nil || o == Undefined {
return nil
}
a := Global.Get("Object").Call("keys", o)
s := make([]string, a.Length())
for i := 0; i < a.Length(); i++ {
s[i] = a.Index(i).String()
}
return s
}
// MakeWrapper creates a JavaScript object which has wrappers for the exported methods of i. Use explicit getter and setter methods to expose struct fields to JavaScript.
func MakeWrapper(i interface{}) *Object {
v := InternalObject(i)
o := Global.Get("Object").New()
o.Set("__internal_object__", v)
methods := v.Get("constructor").Get("methods")
for i := 0; i < methods.Length(); i++ {
m := methods.Index(i)
if m.Get("pkg").String() != "" { // not exported
continue
}
o.Set(m.Get("name").String(), func(args ...*Object) *Object {
return Global.Call("$externalizeFunction", v.Get(m.Get("prop").String()), m.Get("typ"), true).Call("apply", v, args)
})
}
return o
}
// NewArrayBuffer creates a JavaScript ArrayBuffer from a byte slice.
func NewArrayBuffer(b []byte) *Object {
slice := InternalObject(b)
offset := slice.Get("$offset").Int()
length := slice.Get("$length").Int()
return slice.Get("$array").Get("buffer").Call("slice", offset, offset+length)
}
// M is a simple map type. It is intended as a shorthand for JavaScript objects (before conversion).
type M map[string]interface{}
// S is a simple slice type. It is intended as a shorthand for JavaScript arrays (before conversion).
type S []interface{}
func init() {
// avoid dead code elimination
e := Error{}
_ = e
}

1
vendor/github.com/oov/psd/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
output/

149
vendor/github.com/oov/psd/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,149 @@
# PSD/PSB(Photoshop) file reader for Go programming language
It works almost well but it is still in development.
## License
MIT License
Copyright (c) 2016 oov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## How to use
### Example1
Simple psd -> png conversion.
```go
package main
import (
"image"
"image/png"
"os"
_ "github.com/oov/psd"
)
func main() {
file, err := os.Open("image.psd")
if err != nil {
panic(err)
}
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
panic(err)
}
out, err := os.Create("image.png")
if err != nil {
panic(err)
}
err = png.Encode(out, img)
if err != nil {
panic(err)
}
}
```
### Example2
Extract all layer images.
```go
package main
import (
"fmt"
"image/png"
"os"
"github.com/oov/psd"
)
func processLayer(filename string, layerName string, l *psd.Layer) error {
if len(l.Layer) > 0 {
for i, ll := range l.Layer {
if err := processLayer(
fmt.Sprintf("%s_%03d", filename, i),
layerName+"/"+ll.Name, &ll); err != nil {
return err
}
}
}
if !l.HasImage() {
return nil
}
fmt.Printf("%s -> %s.png\n", layerName, filename)
out, err := os.Create(fmt.Sprintf("%s.png", filename))
if err != nil {
return err
}
defer out.Close()
return png.Encode(out, l.Picker)
}
func main() {
file, err := os.Open("image.psd")
if err != nil {
panic(err)
}
defer file.Close()
img, _, err := psd.Decode(file, &psd.DecodeOptions{SkipMergedImage: true})
if err != nil {
panic(err)
}
for i, layer := range img.Layer {
if err = processLayer(fmt.Sprintf("%03d", i), layer.Name, &layer); err != nil {
panic(err)
}
}
}
```
# Current status
It is not implemented any blending functions because layer composition isn't covered by this package at present.
- [Image Resource Section](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_69883) is parsed but [Image resource IDs](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_38034) are not defined as constant.
- [Global layer mask info](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_17115) is not parsed.
- [Layer blending ranges data](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_21332) is not parsed.
- [Additinal Layer Information](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1049436) is parsed but keys are almost not defined as constant.
## Color Modes
### Implemented
- Bitmap 1bit
- Grayscale 8bit
- Grayscale 16bit
- Grayscale 32bit
- Indexed
- RGB 8bit
- RGB 16bit
- RGB 32bit
- CMYK 8bit
- CMYK 16bit
### Not implemented
- CMYK 32bit
- Multichannel
- Duotone
- Lab
## Supported Compression Methods
- Raw
- RLE(PackBits)
- ZIP without prediction (not tested)
- ZIP with prediction

103
vendor/github.com/oov/psd/blendmode.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,103 @@
package psd
// BlendMode represents the blend mode.
type BlendMode string
// These blend modes are defined in this document.
//
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_13084
const (
BlendModePassThrough = BlendMode("pass")
BlendModeNormal = BlendMode("norm")
BlendModeDissolve = BlendMode("diss")
BlendModeDarken = BlendMode("dark")
BlendModeMultiply = BlendMode("mul ")
BlendModeColorBurn = BlendMode("idiv")
BlendModeLinearBurn = BlendMode("lbrn")
BlendModeDarkerColor = BlendMode("dkCl")
BlendModeLighten = BlendMode("lite")
BlendModeScreen = BlendMode("scrn")
BlendModeColorDodge = BlendMode("div ")
BlendModeLinearDodge = BlendMode("lddg")
BlendModeLighterColor = BlendMode("lgCl")
BlendModeOverlay = BlendMode("over")
BlendModeSoftLight = BlendMode("sLit")
BlendModeHardLight = BlendMode("hLit")
BlendModeVividLight = BlendMode("vLit")
BlendModeLinearLight = BlendMode("lLit")
BlendModePinLight = BlendMode("pLit")
BlendModeHardMix = BlendMode("hMix")
BlendModeDifference = BlendMode("diff")
BlendModeExclusion = BlendMode("smud")
BlendModeSubtract = BlendMode("fsub")
BlendModeDivide = BlendMode("fdiv")
BlendModeHue = BlendMode("hue ")
BlendModeSaturation = BlendMode("sat ")
BlendModeColor = BlendMode("colr")
BlendModeLuminosity = BlendMode("lum ")
)
// String implements fmt.Stringer interface.
//
// The return value respects blend name that is described in "Compositing and Blending Level 1"(https://www.w3.org/TR/compositing-1/#blending).
func (bm BlendMode) String() string {
switch bm {
case BlendModePassThrough:
return "pass-through"
case BlendModeNormal:
return "normal"
case BlendModeDissolve:
return "dissolve"
case BlendModeDarken:
return "darken"
case BlendModeMultiply:
return "multiply"
case BlendModeColorBurn:
return "color-burn"
case BlendModeLinearBurn:
return "linear-burn"
case BlendModeDarkerColor:
return "darker-color"
case BlendModeLighten:
return "lighten"
case BlendModeScreen:
return "screen"
case BlendModeColorDodge:
return "color-dodge"
case BlendModeLinearDodge:
return "linear-dodge"
case BlendModeLighterColor:
return "lighter-color"
case BlendModeOverlay:
return "overlay"
case BlendModeSoftLight:
return "soft-light"
case BlendModeHardLight:
return "hard-light"
case BlendModeVividLight:
return "vivid-light"
case BlendModeLinearLight:
return "linear-light"
case BlendModePinLight:
return "pin-light"
case BlendModeHardMix:
return "hard-mix"
case BlendModeDifference:
return "difference"
case BlendModeExclusion:
return "exclusion"
case BlendModeSubtract:
return "subtract"
case BlendModeDivide:
return "divide"
case BlendModeHue:
return "hue"
case BlendModeSaturation:
return "saturation"
case BlendModeColor:
return "color"
case BlendModeLuminosity:
return "luminosity"
}
return "unknown-blend-name-" + string(bm)
}

327
vendor/github.com/oov/psd/color/color.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,327 @@
package color
import (
"image/color"
"math"
)
func fromFloat(v, gamma float64) uint32 {
x := math.Pow(v, gamma)
switch {
case x >= 1:
return 0xffff
case x <= 0:
return 0
default:
return uint32(x * 0xffff)
}
}
func toFloat(v uint32, gamma float64) float64 {
return math.Pow(float64(v)/0xffff, gamma)
}
// Gray1 represents an 1-bit monochrome bitmap color.
type Gray1 struct {
Y bool
}
// RGBA implements color.Color interface's method.
func (c Gray1) RGBA() (r, g, b, a uint32) {
if c.Y {
return 0xffff, 0xffff, 0xffff, 0xffff
}
return 0, 0, 0, 0xffff
}
func gray1Model(c color.Color) color.Color {
if _, ok := c.(Gray1); ok {
return c
}
r, g, b, _ := c.RGBA()
y := (299*r + 587*g + 114*b + 500) / 1000
return Gray1{y >= 0x8000}
}
// Gray32 represents a 32-bit float grayscale color.
type Gray32 struct {
Y float32
}
// RGBA implements color.Color interface's method.
func (c Gray32) RGBA() (r, g, b, a uint32) {
const gamma = 1.0 / 2.2
y := fromFloat(float64(c.Y), gamma)
return y, y, y, 0xffff
}
func gray32Model(c color.Color) color.Color {
if _, ok := c.(Gray32); ok {
return c
}
r, g, b, _ := c.RGBA()
y := (299*r + 587*g + 114*b + 500) / 1000
const gamma = 2.2
return Gray32{float32(toFloat(y, gamma))}
}
type NGrayA struct {
Y uint8
A uint8
}
// RGBA implements color.Color interface's method.
func (c NGrayA) RGBA() (uint32, uint32, uint32, uint32) {
y := uint32(c.Y) * 0x101
if c.A == 0xff {
return y, y, y, 0xffff
}
if c.A == 0 {
return 0, 0, 0, 0
}
a := uint32(c.A) * 0x101
y = y * a / 0xffff
return y, y, y, a
}
func nGrayAModel(c color.Color) color.Color {
if _, ok := c.(NGrayA64); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0 {
return NGrayA{0, 0}
}
y := (299*r + 587*g + 114*b + 500) / 1000
if a == 0xffff {
return NGrayA{uint8(y >> 8), 0xff}
}
y = (y * 0xffff) / a
return NGrayA{uint8(y >> 8), uint8(a >> 8)}
}
type NGrayA32 struct {
Y uint16
A uint16
}
// RGBA implements color.Color interface's method.
func (c NGrayA32) RGBA() (uint32, uint32, uint32, uint32) {
y := uint32(c.Y)
if c.A == 0xffff {
return y, y, y, 0xffff
}
if c.A == 0 {
return 0, 0, 0, 0
}
a := uint32(c.A)
y = y * a / 0xffff
return y, y, y, a
}
func nGrayA32Model(c color.Color) color.Color {
if _, ok := c.(NGrayA64); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0 {
return NGrayA32{0, 0}
}
y := (299*r + 587*g + 114*b + 500) / 1000
if a == 0xffff {
return NGrayA32{uint16(y), 0xffff}
}
y = (y * 0xffff) / a
return NGrayA32{uint16(y), uint16(a)}
}
type NGrayA64 struct {
Y float32
A float32
}
// RGBA implements color.Color interface's method.
func (c NGrayA64) RGBA() (uint32, uint32, uint32, uint32) {
y := fromFloat(float64(c.Y), 1.0/2.2)
switch {
case c.A >= 1:
return y, y, y, 0xffff
case c.A <= 0:
return 0, 0, 0, 0
}
a := uint32(c.A * 0xffff)
y = y * a / 0xffff
return y, y, y, a
}
func nGrayA64Model(c color.Color) color.Color {
if _, ok := c.(NGrayA64); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0 {
return NGrayA64{0, 0}
}
y := (299*r + 587*g + 114*b + 500) / 1000
x := float32(toFloat(y, 2.2))
if a == 0xffff {
return NGrayA64{x, 1}
}
xa := float32(a) / 0xffff
return NGrayA64{x / xa, xa}
}
type NRGBA128 struct {
R, G, B, A float32
}
// RGBA implements color.Color interface's method.
func (c NRGBA128) RGBA() (uint32, uint32, uint32, uint32) {
const gamma = 1.0 / 2.2
r := fromFloat(float64(c.R), gamma)
g := fromFloat(float64(c.G), gamma)
b := fromFloat(float64(c.B), gamma)
switch {
case c.A >= 1:
return r, g, b, 0xffff
case c.A <= 0:
return 0, 0, 0, 0
}
a := uint32(c.A * 0xffff)
r = r * a / 0xffff
g = g * a / 0xffff
b = b * a / 0xffff
return r, g, b, a
}
func nRGBA128Model(c color.Color) color.Color {
if _, ok := c.(NRGBA128); ok {
return c
}
r, g, b, a := c.RGBA()
const gamma = 2.2
fr := float32(toFloat(r, gamma))
fg := float32(toFloat(g, gamma))
fb := float32(toFloat(b, gamma))
switch {
case a >= 0xffff:
return NRGBA128{fr, fg, fb, 1}
case a == 0:
return NRGBA128{}
}
fa := 0xffff / float32(a)
fr *= fa
fg *= fa
fb *= fa
return NRGBA128{fr, fg, fb, float32(a) / 0xffff}
}
// NCMYKA represents a non-alpha-premultiplied CMYK color, having 8 bits for each of cyan,
// magenta, yellow, black and alpha.
// NCMYKA is different from color.CMYK, CMYK is inverted value.
//
// It is not associated with any particular color profile.
type NCMYKA struct {
C, M, Y, K, A uint8
}
// RGBA implements color.Color interface's method.
func (c NCMYKA) RGBA() (uint32, uint32, uint32, uint32) {
w := uint32(c.K) * 0x10201
r := uint32(c.C) * w / 0xffff
g := uint32(c.M) * w / 0xffff
b := uint32(c.Y) * w / 0xffff
if c.A == 0xff {
return r, g, b, 0xffff
}
if c.A == 0 {
return 0, 0, 0, 0
}
a := uint32(c.A) * 0x101
r = r * a / 0xffff
g = g * a / 0xffff
b = b * a / 0xffff
return r, g, b, a
}
func nCMYKAModel(c color.Color) color.Color {
if _, ok := c.(NCMYKA); ok {
return c
}
r, g, b, a := c.RGBA()
cc, mm, yy, kk := color.RGBToCMYK(uint8(r>>8), uint8(g>>8), uint8(b>>8))
cc = uint8((uint32(cc) * 0xffff) / a)
mm = uint8((uint32(mm) * 0xffff) / a)
yy = uint8((uint32(yy) * 0xffff) / a)
kk = uint8((uint32(kk) * 0xffff) / a)
return NCMYKA{255 - cc, 255 - mm, 255 - yy, 255 - kk, uint8(a >> 8)}
}
type NCMYKA80 struct {
C, M, Y, K, A uint16
}
// RGBA implements color.Color interface's method.
func (c NCMYKA80) RGBA() (uint32, uint32, uint32, uint32) {
w := uint32(c.K)
r := uint32(c.C) * w / 0xffff
g := uint32(c.M) * w / 0xffff
b := uint32(c.Y) * w / 0xffff
if c.A == 0xffff {
return r, g, b, 0xffff
}
if c.A == 0 {
return 0, 0, 0, 0
}
a := uint32(c.A)
r = r * a / 0xffff
g = g * a / 0xffff
b = b * a / 0xffff
return r, g, b, a
}
func nCMYKA80Model(c color.Color) color.Color {
if _, ok := c.(NCMYKA); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0 {
return NCMYKA80{0xffff, 0xffff, 0xffff, 0xffff, 0}
}
w := r
if w < g {
w = g
}
if w < b {
w = b
}
if w == 0 {
return NCMYKA80{0xffff, 0xffff, 0xffff, 0xffff, uint16(a)}
}
cc := (w - r) * 0xffff / w
mm := (w - g) * 0xffff / w
yy := (w - b) * 0xffff / w
kk := 0xffff - w
if a == 0xffff {
return NCMYKA80{uint16(0xffff - cc), uint16(0xffff - mm), uint16(0xffff - yy), uint16(0xffff - kk), 0xffff}
}
cc = (cc * 0xffff) / a
mm = (mm * 0xffff) / a
yy = (yy * 0xffff) / a
kk = (kk * 0xffff) / a
return NCMYKA80{uint16(0xffff - cc), uint16(0xffff - mm), uint16(0xffff - yy), uint16(0xffff - kk), uint16(a)}
}
// These are color model.
var (
Gray1Model = color.ModelFunc(gray1Model)
NGrayAModel = color.ModelFunc(nGrayAModel)
Gray32Model = color.ModelFunc(gray32Model)
NGrayA32Model = color.ModelFunc(nGrayA32Model)
NGrayA64Model = color.ModelFunc(nGrayA64Model)
NRGBA128Model = color.ModelFunc(nRGBA128Model)
NCMYKAModel = color.ModelFunc(nCMYKAModel)
NCMYKA80Model = color.ModelFunc(nCMYKA80Model)
)

34
vendor/github.com/oov/psd/colormode.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
package psd
// ColorMode represents color mode that is used in psd file.
type ColorMode int16
// These color modes are defined in this document.
//
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_19840
const (
ColorModeBitmap = ColorMode(0)
ColorModeGrayscale = ColorMode(1)
ColorModeIndexed = ColorMode(2)
ColorModeRGB = ColorMode(3)
ColorModeCMYK = ColorMode(4)
ColorModeMultichannel = ColorMode(7)
ColorModeDuotone = ColorMode(8)
ColorModeLab = ColorMode(9)
)
// Channels returns the number of channels for the color mode.
// The return value is not including alpha channel.
func (c ColorMode) Channels() int {
switch c {
case ColorModeBitmap,
ColorModeGrayscale,
ColorModeIndexed:
return 1
case ColorModeRGB:
return 3
case ColorModeCMYK:
return 4
}
return -1
}

90
vendor/github.com/oov/psd/compress.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,90 @@
package psd
import (
"compress/zlib"
"errors"
"image"
"io"
)
// CompressionMethod represents compression method that is used in psd file.
type CompressionMethod int16
// These compression methods are defined in this document.
//
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1054855
const (
CompressionMethodRaw = CompressionMethod(0)
CompressionMethodRLE = CompressionMethod(1)
CompressionMethodZIPWithoutPrediction = CompressionMethod(2)
CompressionMethodZIPWithPrediction = CompressionMethod(3)
)
// Decode decodes the compressed image data from r.
//
// You can pass 0 to sizeHint if unknown, but in this case may read more data than necessary from r.
func (cm CompressionMethod) Decode(dest []byte, r io.Reader, sizeHint int64, rect image.Rectangle, depth int, channels int, large bool) (read int, err error) {
switch cm {
case CompressionMethodRaw:
return io.ReadFull(r, dest)
case CompressionMethodRLE:
return decodePackBits(dest, r, rect.Dx(), rect.Dy()*channels, large)
case CompressionMethodZIPWithoutPrediction:
return decodeZLIB(dest, r, sizeHint)
case CompressionMethodZIPWithPrediction:
if read, err = decodeZLIB(dest, r, sizeHint); err != nil {
return read, err
}
decodeDelta(dest, rect.Dx(), depth)
return read, err
}
return 0, errors.New("psd: compression method " + itoa(int(cm)) + " is not implemented")
}
// decodeZLIB decodes compressed data by zlib.
// You can pass 0 to length if unknown,
// but in that case may read more data than necessary from r.
func decodeZLIB(dest []byte, r io.Reader, length int64) (read int, err error) {
N := length
if N == 0 {
N = 0x7fffffffffffffff
}
lr := &io.LimitedReader{R: r, N: N}
zr, err := zlib.NewReader(lr)
if err != nil {
return 0, err
}
if _, err = io.ReadFull(zr, dest); err != nil {
zr.Close()
return int(N - lr.N), err
}
if err = zr.Close(); err != nil {
return int(N - lr.N), err
}
return int(N - lr.N), nil
}
func decodeDelta(buf []byte, width int, depth int) {
switch depth {
case 16:
var d uint16
for i := 0; i < len(buf); {
d = 0
for j := 0; j < width; j++ {
d += readUint16(buf, i)
writeUint16(buf, d, i)
i += 2
}
}
case 32:
var d uint32
for i := 0; i < len(buf); {
d = 0
for j := 0; j < width; j++ {
d += readUint32(buf, i)
writeUint32(buf, d, i)
i += 4
}
}
}
}

41
vendor/github.com/oov/psd/compress.inc.js сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,41 @@
$global['$github.com/oov/psd$'] = {
decodePackBitsLines: function(buf, lines, large) {
var r = new Uint32Array(lines);
var lens = new DataView(buf.buffer);
if (large) {
for (var i = 0; i < lines; ++i) {
r[i] = lens.getUint32(i << 2, false);
}
} else {
for (var i = 0; i < lines; ++i) {
r[i] = lens.getUint16(i << 1, false);
}
}
return r;
},
decodePackBits: function(dest, buf, lens) {
var ofs = 0,
d = 0;
for (var i = 0; i < lens.length; ++i) {
for (var j = 0, ln = lens[i]; j < ln;) {
if (buf[ofs] <= 0x7f) {
var l = buf[ofs++] + 1;
for (var k = 0; k < l; ++k) {
dest[d++] = buf[ofs++];
}
j += l + 1;
continue;
}
if (buf[ofs] == 0x80) {
ofs++;
continue;
}
for (var k = 0, l = 256 - buf[ofs++] + 1, c = buf[ofs++]; k < l; ++k) {
dest[d++] = c;
}
j += 2;
}
}
return true;
}
}

40
vendor/github.com/oov/psd/compress_js.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,40 @@
// +build !wasm
// +build js
package psd
import (
"errors"
"io"
"github.com/gopherjs/gopherjs/js"
)
func decodePackBits(dest []byte, r io.Reader, width int, lines int, large bool) (read int, err error) {
intSize := get4or8(large) >> 1
b := make([]byte, lines*intSize)
var l int
if l, err = io.ReadFull(r, b); err != nil {
return
}
read += l
lens := js.Global.Get("$github.com/oov/psd$").Call("decodePackBitsLines", b, lines, large).Interface().([]uint)
if lens == nil {
return read, errors.New("psd: error occurred in decodePackBitsLines")
}
total := uint(0)
for _, ln := range lens {
total += ln
}
b = make([]byte, total)
if l, err = io.ReadFull(r, b); err != nil {
return
}
read += l
if !js.Global.Get("$github.com/oov/psd$").Call("decodePackBits", dest, b, lens).Bool() {
return read, errors.New("psd: error occurred in decodePackBits")
}
return
}

99
vendor/github.com/oov/psd/compress_other.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,99 @@
// +build !js
package psd
import (
"io"
"runtime"
"sync"
)
func decodePackBits(dest []byte, r io.Reader, width int, lines int, large bool) (read int, err error) {
buf := make([]byte, lines*(get4or8(large)>>1))
var l int
if l, err = io.ReadFull(r, buf); err != nil {
return
}
read += l
total := 0
lens := make([]int, lines)
offsets := make([]int, lines)
ofs := 0
if large {
for i := range lens {
l = int(readUint32(buf, ofs))
lens[i] = l
offsets[i] = total
total += l
ofs += 4
}
} else {
for i := range lens {
l = int(readUint16(buf, ofs))
lens[i] = l
offsets[i] = total
total += l
ofs += 2
}
}
buf = make([]byte, total)
if l, err = io.ReadFull(r, buf); err != nil {
return
}
read += l
n := runtime.GOMAXPROCS(0)
for n > 1 && n<<1 > lines {
n--
}
if n == 1 {
decodePackBitsPerLine(dest, buf, lens)
return
}
var wg sync.WaitGroup
wg.Add(n)
step := lines / n
ofs = 0
for i := 1; i < n; i++ {
go func(dest []byte, buf []byte, lens []int) {
defer wg.Done()
decodePackBitsPerLine(dest, buf, lens)
}(dest[ofs*width:(ofs+step)*width], buf[offsets[ofs]:offsets[ofs+step]], lens[ofs:ofs+step])
ofs += step
}
go func() {
defer wg.Done()
decodePackBitsPerLine(dest[ofs*width:], buf[offsets[ofs]:], lens[ofs:])
}()
wg.Wait()
return
}
func decodePackBitsPerLine(dest []byte, buf []byte, lens []int) {
var l int
for _, ln := range lens {
for i := 0; i < ln; {
if buf[i] <= 0x7f {
l = int(buf[i]) + 1
copy(dest[:l], buf[i+1:])
dest = dest[l:]
i += l + 1
continue
}
if buf[i] == 0x80 {
i++
continue
}
l = int(-buf[i]) + 1
for j, c := 0, buf[i+1]; j < l; j++ {
dest[j] = c
}
dest = dest[l:]
i += 2
}
buf = buf[ln:]
}
}

99
vendor/github.com/oov/psd/compress_wasm_js.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,99 @@
// +build wasm,js
package psd
import (
"io"
"runtime"
"sync"
)
func decodePackBits(dest []byte, r io.Reader, width int, lines int, large bool) (read int, err error) {
buf := make([]byte, lines*(get4or8(large)>>1))
var l int
if l, err = io.ReadFull(r, buf); err != nil {
return
}
read += l
total := 0
lens := make([]int, lines)
offsets := make([]int, lines)
ofs := 0
if large {
for i := range lens {
l = int(readUint32(buf, ofs))
lens[i] = l
offsets[i] = total
total += l
ofs += 4
}
} else {
for i := range lens {
l = int(readUint16(buf, ofs))
lens[i] = l
offsets[i] = total
total += l
ofs += 2
}
}
buf = make([]byte, total)
if l, err = io.ReadFull(r, buf); err != nil {
return
}
read += l
n := runtime.GOMAXPROCS(0)
for n > 1 && n<<1 > lines {
n--
}
if n == 1 {
decodePackBitsPerLine(dest, buf, lens)
return
}
var wg sync.WaitGroup
wg.Add(n)
step := lines / n
ofs = 0
for i := 1; i < n; i++ {
go func(dest []byte, buf []byte, lens []int) {
defer wg.Done()
decodePackBitsPerLine(dest, buf, lens)
}(dest[ofs*width:(ofs+step)*width], buf[offsets[ofs]:offsets[ofs+step]], lens[ofs:ofs+step])
ofs += step
}
go func() {
defer wg.Done()
decodePackBitsPerLine(dest[ofs*width:], buf[offsets[ofs]:], lens[ofs:])
}()
wg.Wait()
return
}
func decodePackBitsPerLine(dest []byte, buf []byte, lens []int) {
var l int
for _, ln := range lens {
for i := 0; i < ln; {
if buf[i] <= 0x7f {
l = int(buf[i]) + 1
copy(dest[:l], buf[i+1:])
dest = dest[l:]
i += l + 1
continue
}
if buf[i] == 0x80 {
i++
continue
}
l = int(-buf[i]) + 1
for j, c := 0, buf[i+1]; j < l; j++ {
dest[j] = c
}
dest = dest[l:]
i += 2
}
buf = buf[ln:]
}
}

108
vendor/github.com/oov/psd/imageres.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,108 @@
package psd
import (
"errors"
"io"
)
// ImageResource represents the image resource that is used in psd file.
type ImageResource struct {
Name string
Data []byte
}
func readImageResource(r io.Reader) (resMap map[int]ImageResource, read int, err error) {
if Debug != nil {
Debug.Println("start - image resources section")
}
// Image Resources Section
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_69883
var l int
b := make([]byte, 6)
if l, err = io.ReadFull(r, b[:4]); err != nil {
return nil, 0, err
}
read += l
imageResourceLen := int(readUint32(b, 0))
if imageResourceLen == 0 {
return map[int]ImageResource{}, read, nil
}
resMap = map[int]ImageResource{}
// Image Resource Blocks
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_46269
var id int
for read < imageResourceLen {
var res ImageResource
// Signature: '8BIM'
if l, err = io.ReadFull(r, b[:6]); err != nil {
return nil, read, err
}
read += l
if string(b[:4]) != "8BIM" {
return nil, read, errors.New("psd: invalid image resource signature")
}
// Unique identifier for the resource.
// Image resource IDs contains a list of resource IDs used by Photoshop.
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_38034
id = int(readUint16(b, 4))
// Name: Pascal string, padded to make the size even
// (a null name consists of two bytes of 0)
if res.Name, l, err = readPascalString(r); err != nil {
return nil, read, err
}
read += l
if l, err = adjustAlign2(r, l); err != nil {
return nil, read, err
}
read += l
// The resource data, described in the sections on the individual resource types.
// It is padded to make the size even.
if l, err = io.ReadFull(r, b[:4]); err != nil {
return nil, read, err
}
read += l
res.Data = make([]byte, readUint32(b, 0))
if l, err = io.ReadFull(r, res.Data); err != nil {
return nil, read, err
}
read += l
if l, err = adjustAlign2(r, l); err != nil {
return nil, read, err
}
read += l
if Debug != nil {
Debug.Printf(" id: %04x(%d) name: %s dataLen: %d", id, id, res.Name, len(res.Data))
}
resMap[id] = res
}
if Debug != nil {
Debug.Println("end - image resources section")
}
return resMap, read, nil
}
func hasAlphaID0(Res map[int]ImageResource) bool {
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_38034
// 0x041D(1053) | (Photoshop 6.0) Alpha Identifiers.
// 4 bytes of length, followed by 4 bytes each for every alpha identifier.
//
// This description is probably a little different from the actual structure.
// "4 bytes of length" is included in Image Resource Blocks structure, not in the resource data block.
// so alpha identifier appears from the head in the resource data block.
aid, ok := Res[0x041D]
if !ok {
return true
}
for i, ln := 0, len(aid.Data); i < ln; i += 4 {
if readUint32(aid.Data, i) == 0 {
return true
}
}
return false
}

875
vendor/github.com/oov/psd/layer.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,875 @@
package psd
import (
"errors"
"image"
"io"
)
// Layer represents layer.
type Layer struct {
SeqID int
Name string
UnicodeName string
MBCSName string
Rect image.Rectangle
// Channel key is the channel ID.
// 0 = red, 1 = green, etc.
// -1 = transparency mask
// -2 = user supplied layer mask
// -3 = real user supplied layer mask
// (when both a user mask and a vector mask are present)
Channel map[int]Channel
BlendMode BlendMode
Opacity uint8
Clipping bool
BlendClippedElements bool
Flags uint8
Mask Mask
Picker image.Image
AdditionalLayerInfo map[AdditionalInfoKey][]byte
SectionDividerSetting struct {
Type int
BlendMode BlendMode
SubType int
}
Layer []Layer
}
// TransparencyProtected returns whether the layer's transparency being protected.
func (l *Layer) TransparencyProtected() bool {
return l.Flags&1 != 0
}
// Visible returns whether the layer is visible.
func (l *Layer) Visible() bool {
return l.Flags&2 == 0
}
// HasImage returns whether the layer has an image data.
func (l *Layer) HasImage() bool {
return l.SectionDividerSetting.Type == 0
}
// Folder returns whether the layer is folder(group layer).
func (l *Layer) Folder() bool {
return l.SectionDividerSetting.Type == 1 || l.SectionDividerSetting.Type == 2
}
// FolderIsOpen returns whether the folder is opened when layer is folder.
func (l *Layer) FolderIsOpen() bool {
return l.SectionDividerSetting.Type == 1
}
func (l *Layer) String() string {
return l.Name
}
// Mask represents layer mask and vector mask.
type Mask struct {
Rect image.Rectangle
DefaultColor int
Flags int
RealRect image.Rectangle
RealBackgroundColor int
RealFlags int
UserMaskDensity int
UserMaskFeather float64
VectorMaskDensity int
VectorMaskFeather float64
}
// Enabled returns whether the mask is enabled.
func (m *Mask) Enabled() bool {
return m.Flags&2 == 0
}
// RealEnabled returns whether the user real mask is enabled.
func (m *Mask) RealEnabled() bool {
return m.RealFlags&2 == 0
}
// Channel represents a channel of the color.
type Channel struct {
// Data is uncompressed channel image data.
Data []byte
Picker image.Image
}
func readLayerAndMaskInfo(r io.Reader, cfg *Config, o *DecodeOptions) (psd *PSD, read int, err error) {
if Debug != nil {
Debug.Println("start - layer and mask information section")
}
psd = &PSD{
Config: *cfg,
}
// Layer and Mask Information Section
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_75067
intSize := get4or8(cfg.PSB())
b := make([]byte, intSize)
var l int
if l, err = io.ReadFull(r, b[:intSize]); err != nil {
return nil, 0, err
}
read += l
layerAndMaskInfoLen := int(readUint(b, 0, intSize))
if Debug != nil {
Debug.Println(" layerAndMaskInfoLen:", layerAndMaskInfoLen)
reportReaderPosition(" file offset: 0x%08x", r)
}
if layerAndMaskInfoLen == 0 {
return psd, read, nil
}
var layer []Layer
if read < layerAndMaskInfoLen+intSize {
if layer, l, err = readLayerInfo(r, cfg, o); err != nil {
return nil, read, err
}
read += l
}
if layerAndMaskInfoLen+intSize-read >= 4 {
// Global layer mask info
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_17115
if l, err = io.ReadFull(r, b[:4]); err != nil {
return nil, read, err
}
read += l
if globalLayerMaskInfoLen := int(readUint32(b, 0)); globalLayerMaskInfoLen > 0 {
if Debug != nil {
Debug.Println(" globalLayerMaskInfoLen:", globalLayerMaskInfoLen)
reportReaderPosition(" file offset: 0x%08x", r)
}
// TODO(oov): implement
if l, err = io.ReadFull(r, make([]byte, globalLayerMaskInfoLen)); err != nil {
return nil, read, err
}
read += l
}
}
if layerAndMaskInfoLen+intSize-read >= 8 {
var layer2 []Layer
if psd.AdditinalLayerInfo, layer2, l, err = readAdditionalLayerInfo(r, layerAndMaskInfoLen+intSize-read, cfg, o); err != nil {
return nil, read, err
}
read += l
if layer != nil && layer2 != nil {
return nil, read, errors.New("psd: unexpected layer structure")
}
if layer2 != nil {
layer = layer2
}
}
if psd.Layer, err = buildTree(layer); err != nil {
return nil, read, err
}
if remain := layerAndMaskInfoLen + intSize - read; remain != 0 && remain < intSize {
if l, err = discard(r, remain); err != nil {
return nil, read, err
}
read += l
}
if read != layerAndMaskInfoLen+intSize {
return nil, read, errors.New("psd: layer and mask info read size mismatched. expected " + itoa(layerAndMaskInfoLen+4) + " actual " + itoa(read))
}
if Debug != nil {
Debug.Println("end - layer and mask information section")
}
return psd, read, nil
}
func buildTree(layer []Layer) ([]Layer, error) {
// idx type
// 0: 3
// 1: 3
// 2: 0
// 3: 0
// 4: 1
// 5: 0
// 6: 0
// 7: 1
stack := make([][]Layer, 0, 8)
n := []Layer{}
for i, l := range layer {
switch l.SectionDividerSetting.Type {
case 1, 2:
l.Layer = n
if len(stack) == 0 {
return nil, errors.New("psd: layer tree structure is broken(#" + itoa(i) + ")")
}
n = stack[len(stack)-1]
stack = stack[:len(stack)-1]
n = append(n, l)
case 3:
stack = append(stack, n)
n = []Layer{}
default:
n = append(n, l)
}
}
return n, nil
}
func readSectionDividerSetting(l *Layer) (typ int, blendMode BlendMode, subType int, err error) {
b, ok := l.AdditionalLayerInfo[AdditionalInfoKeySectionDividerSetting]
if ok {
typ = int(readUint32(b, 0))
if len(b) < 12 {
return typ, "", 0, nil
}
if string(b[4:8]) != sectionSignature {
return 0, "", 0, errors.New("psd: unexpected signature in section divider setting")
}
blendMode = BlendMode(b[8:12])
if len(b) < 16 {
return typ, blendMode, 0, nil
}
subType = int(readUint32(b, 12))
return typ, blendMode, subType, nil
}
b, ok = l.AdditionalLayerInfo[AdditionalInfoKeySectionDividerSetting2]
if ok {
typ = int(readUint32(b, 0))
if len(b) < 12 {
return typ, "", 0, nil
}
if string(b[4:8]) != sectionSignature {
return 0, "", 0, errors.New("psd: unexpected signature in section divider setting 2")
}
blendMode = BlendMode(b[8:12])
if len(b) < 16 {
return typ, blendMode, 0, nil
}
subType = int(readUint32(b, 12))
return typ, blendMode, subType, nil
}
return 0, "", 0, nil
}
type channelData struct {
ChIndex int
DataLen int
}
type layerChannelInfo struct {
Layer *Layer
ChannelData []channelData
}
func readLayerInfo(r io.Reader, cfg *Config, o *DecodeOptions) (layer []Layer, read int, err error) {
intSize := get4or8(cfg.PSB())
if Debug != nil {
Debug.Println("start - layer info section")
}
b := make([]byte, 16)
var l int
if l, err = io.ReadFull(r, b[:intSize]); err != nil {
return nil, 0, err
}
read += l
layerInfoLen := int(readUint(b, 0, intSize))
if Debug != nil {
Debug.Println(" layerInfoLen:", layerInfoLen)
}
if layerInfoLen == 0 {
if Debug != nil {
Debug.Println("end - layer info section")
}
return nil, read, nil
}
if l, err = io.ReadFull(r, b[:2]); err != nil {
return nil, read, err
}
read += l
numLayers := readUint16(b, 0)
if numLayers&0x8000 != 0 {
numLayers = ^numLayers + 1
// how can I use this info...?
// hasAlphaForMergedResult = true
}
if Debug != nil {
Debug.Println(" numLayers:", numLayers)
}
layerSlice := make([]Layer, numLayers)
lcis := make([]layerChannelInfo, numLayers)
for i := range layerSlice {
if Debug != nil {
Debug.Printf("start - layer #%d structure", i)
}
layer := &layerSlice[i]
layer.SeqID = i
if l, err = io.ReadFull(r, b[:16]); err != nil {
return nil, read, err
}
read += l
layer.Rect = image.Rect(
int(int32(readUint32(b, 4))), int(int32(readUint32(b, 0))),
int(int32(readUint32(b, 12))), int(int32(readUint32(b, 8))),
)
if l, err = io.ReadFull(r, b[:2]); err != nil {
return nil, read, err
}
read += l
numChannels := int(readUint16(b, 0))
lci := layerChannelInfo{
Layer: layer,
ChannelData: make([]channelData, numChannels),
}
for j := 0; j < numChannels; j++ {
if l, err = io.ReadFull(r, b[:2+intSize]); err != nil {
return nil, read, err
}
read += l
lci.ChannelData[j] = channelData{
ChIndex: int(int16(readUint16(b, 0))),
DataLen: int(readUint(b, 2, intSize)),
}
}
lcis[i] = lci
if l, err = io.ReadFull(r, b[:12]); err != nil {
return nil, read, err
}
read += l
if string(b[:4]) != sectionSignature {
return nil, read, errors.New("psd: unexpected the blend mode signature")
}
layer.BlendMode = BlendMode(b[4:8])
layer.Opacity = b[8]
layer.Clipping = b[9] != 0
layer.Flags = b[10]
// b[11] - Filler(zero)
if l, err = readLayerExtraData(r, layer, cfg, o); err != nil {
return nil, read, err
}
read += l
if data, ok := layer.AdditionalLayerInfo[AdditionalInfoKeyUnicodeLayerName]; ok && data != nil {
layer.UnicodeName = readUnicodeString(data)
layer.Name = layer.UnicodeName
delete(layer.AdditionalLayerInfo, AdditionalInfoKeyUnicodeLayerName)
} else {
layer.Name = layer.MBCSName
}
// this is called "Blend Clipped Layers as Group" in Photoshop's Layer Style dialog.
if data, ok := layer.AdditionalLayerInfo[AdditionalInfoKeyBlendClippingElements]; ok && data != nil {
layer.BlendClippedElements = data[0] != 0
delete(layer.AdditionalLayerInfo, AdditionalInfoKeyBlendClippingElements)
} else {
layer.BlendClippedElements = true
}
if layer.SectionDividerSetting.Type,
layer.SectionDividerSetting.BlendMode,
layer.SectionDividerSetting.SubType,
err = readSectionDividerSetting(layer); err != nil {
return nil, read, err
}
if layer.SectionDividerSetting.BlendMode == "" {
layer.SectionDividerSetting.BlendMode = layer.BlendMode
}
delete(layer.AdditionalLayerInfo, AdditionalInfoKeySectionDividerSetting)
if Debug != nil {
Debug.Printf("layer #%d", layer.SeqID)
Debug.Println(" Name:", layer.Name)
Debug.Println(" Rect:", layer.Rect)
Debug.Println(" Channels:", len(layer.Channel))
Debug.Println(" BlendMode:", layer.BlendMode)
Debug.Println(" Opacity:", layer.Opacity)
Debug.Println(" Clipping:", layer.Clipping)
Debug.Println(" Flags:", layer.Flags)
Debug.Println(" TransparecyProtected:", layer.TransparencyProtected())
Debug.Println(" Visible:", layer.Visible())
Debug.Println(" Photoshop 5.0 and later:", layer.Flags&8 != 0)
// this information is useful for the group layer,
// but sadly it isn't written correctly by some other softwares.
Debug.Println(" Pixel data irrelevant to appearance of document:", layer.Flags&8 != 0 && layer.Flags&16 != 0)
Debug.Println(" SectionDividerSetting:")
Debug.Println(" Type:", layer.SectionDividerSetting.Type)
Debug.Println(" BlendMode:", layer.SectionDividerSetting.BlendMode)
Debug.Println(" SubType:", layer.SectionDividerSetting.SubType)
Debug.Println(" LayerMask:")
Debug.Println(" Rect:", layer.Mask.Rect)
Debug.Println(" DefaultColor:", layer.Mask.DefaultColor)
Debug.Println(" Flags:", layer.Mask.Flags)
Debug.Println(" Position relative to layer:", layer.Mask.Flags&1 != 0)
Debug.Println(" Layer mask enabled:", layer.Mask.Enabled())
Debug.Println(" Invert layer mask when blending (Obsolete):", layer.Mask.Flags&4 != 0)
Debug.Println(" The user mask actually came from rendering other data:", layer.Mask.Flags&8 != 0)
Debug.Printf("end - layer #%d structure", i)
}
}
if !o.SkipLayerImage {
if l, err = readLayerImage(lcis, r, cfg, o); err != nil {
return nil, read, err
}
read += l
if l, err = adjustAlign4(r, read+4-layerInfoLen); err != nil {
return nil, read, err
}
read += l
} else {
if l, err = discard(r, layerInfoLen+4-read); err != nil {
return nil, read, err
}
read += l
}
if layerInfoLen+intSize != read {
return nil, read, errors.New("psd: layer info read size mismatched. expected " + itoa(layerInfoLen+4) + " actual " + itoa(read))
}
if Debug != nil {
Debug.Println("end - layer info section")
}
return layerSlice, read, nil
}
func readLayerImage(lcis []layerChannelInfo, r io.Reader, cfg *Config, o *DecodeOptions) (read int, err error) {
var l int
b := make([]byte, 2)
for i, lci := range lcis {
chMap := map[int]Channel{}
pickerChs := make([][]byte, cfg.ColorMode.Channels(), 8)
for _, j := range lci.ChannelData {
var readCh int
if j.DataLen >= 2 {
if l, err = io.ReadFull(r, b[:2]); err != nil {
return read, err
}
readCh += l
read += l
}
cmpMethod := CompressionMethod(readUint16(b, 0))
if Debug != nil {
Debug.Printf(" layer #%d %q channel #%d image data", i, lci.Layer.Name, j.ChIndex)
Debug.Println(" length:", j.DataLen, "compression method:", cmpMethod)
reportReaderPosition(" file offset: 0x%08x", r)
}
var rect image.Rectangle
switch j.ChIndex {
case -3:
rect = lci.Layer.Mask.RealRect
case -2:
rect = lci.Layer.Mask.Rect
default:
rect = lci.Layer.Rect
}
data := make([]byte, (rect.Dx()*cfg.Depth+7)>>3*rect.Dy())
pk := findGrayPicker(cfg.Depth)
pk.setSource(rect, data)
if j.DataLen > 2 {
if l, err = cmpMethod.Decode(data, r, int64(j.DataLen-2), rect, cfg.Depth, 1, cfg.PSB()); err != nil {
return read, err
}
readCh += l
read += l
}
// It seems we can discard in this case
if readCh < j.DataLen {
if l, err = discard(r, j.DataLen-readCh); err != nil {
return read, err
}
readCh += l
read += l
}
if readCh != j.DataLen {
return read, errors.New("psd: layer: " + itoa(i) + " channel: " + itoa(j.ChIndex) + " read size mismatched. expected " + itoa(j.DataLen) + " actual " + itoa(readCh))
}
chMap[j.ChIndex] = Channel{
Data: data,
Picker: pk,
}
switch {
case j.ChIndex >= 0:
pickerChs[j.ChIndex] = data
case j.ChIndex == -1:
pickerChs = append(pickerChs, data)
}
}
pk := findPicker(cfg.Depth, cfg.ColorMode, cfg.ColorMode.Channels() < len(pickerChs))
pk.setSource(lci.Layer.Rect, pickerChs...)
lci.Layer.Picker = pk
lci.Layer.Channel = chMap
if o.LayerImageLoaded != nil {
o.LayerImageLoaded(lci.Layer, i, len(lcis))
}
}
return read, nil
}
func readLayerExtraData(r io.Reader, layer *Layer, cfg *Config, o *DecodeOptions) (read int, err error) {
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_22582
// Layer mask / adjustment layer data
if Debug != nil {
Debug.Println("start - layer extra data section")
}
b := make([]byte, 16)
var l int
if l, err = io.ReadFull(r, b[:4]); err != nil {
return 0, err
}
read += l
extraDataLen := int(readUint32(b, 0))
if Debug != nil {
Debug.Println(" extraDataLen:", extraDataLen)
}
if extraDataLen == 0 {
return read, err
}
l, err = readLayerMaskAndAdjustmentLayerData(r, layer, cfg, o)
read += l
if err != nil {
return read, err
}
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_21332
// Layer blending ranges data
if l, err = io.ReadFull(r, b[:4]); err != nil {
return read, err
}
read += l
if blendingRangesLen := int(readUint32(b, 0)); blendingRangesLen > 0 {
if Debug != nil {
Debug.Println(" layer blending ranges data skipped:", blendingRangesLen)
}
// TODO(oov): implement
if l, err = io.ReadFull(r, make([]byte, blendingRangesLen)); err != nil {
return read, err
}
read += l
}
// Layer name: Pascal string, padded to a multiple of 4 bytes.
if layer.MBCSName, l, err = readPascalString(r); err != nil {
return read, err
}
read += l
if l, err = adjustAlign4(r, l); err != nil {
return read, err
}
read += l
if read < extraDataLen+4 {
var layers []Layer
if layer.AdditionalLayerInfo, layers, l, err = readAdditionalLayerInfo(r, extraDataLen+4-read, cfg, o); err != nil {
return read, err
}
read += l
if len(layers) > 0 {
return read, errors.New("psd: unexpected layer structure")
}
} else {
layer.AdditionalLayerInfo = map[AdditionalInfoKey][]byte{}
}
if extraDataLen+4 != read {
return read, errors.New("psd: layer extra info read size mismatched. expected " + itoa(extraDataLen+4) + " actual " + itoa(read))
}
if Debug != nil {
Debug.Println("end - layer extra data section")
}
return read, nil
}
func readLayerMaskAndAdjustmentLayerData(r io.Reader, layer *Layer, cfg *Config, o *DecodeOptions) (read int, err error) {
// Layer mask / adjustment layer data
// Can be 40 bytes, 24 bytes, or 4 bytes if no layer mask.
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_22582
var l int
b := make([]byte, 16)
if l, err = io.ReadFull(r, b[:4]); err != nil {
return read, err
}
read += l
maskLen := int(readUint32(b, 0))
if maskLen == 0 {
// no layer mask
return read, nil
}
var readMask int
if maskLen-readMask < 16 {
// "Rectangle enclosing layer mask" is not present.
if maskLen-readMask > 0 {
l, err = discard(r, maskLen-readMask)
read += l
if err != nil {
return read, err
}
}
return read, nil
}
if l, err = io.ReadFull(r, b[:16]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.Rect = image.Rect(
int(int32(readUint32(b, 4))), int(int32(readUint32(b, 0))),
int(int32(readUint32(b, 12))), int(int32(readUint32(b, 8))),
)
if maskLen-readMask < 1 {
// "Default color" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.DefaultColor = int(b[0])
// bit 0 = position relative to layer
// bit 1 = layer mask disabled
// bit 2 = invert layer mask when blending (Obsolete)
// bit 3 = indicates that the user mask actually came from rendering other data
// bit 4 = indicates that the user and/or vector masks have parameters applied to them
if maskLen-readMask < 1 {
// "Flags" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.Flags = int(b[0])
layer.Mask.UserMaskDensity = 255
layer.Mask.VectorMaskDensity = 255
// Mask Parameters. Only present if bit 4 of Flags set above.
if layer.Mask.Flags&16 != 0 {
if maskLen-readMask < 1 {
// "Mask Parameters" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
// Mask Parameters bit flags present as follows:
// bit 0 = user mask density, 1 byte
// bit 1 = user mask feather, 8 byte, double
// bit 2 = vector mask density, 1 byte
// bit 3 = vector mask feather, 8 bytes, double
maskParam := int(b[0])
if maskParam&1 != 0 {
if maskLen-readMask < 1 {
// "user mask density" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.UserMaskDensity = int(b[0])
}
if maskParam&2 != 0 {
if maskLen-readMask < 8 {
// "user mask feather" is not present.
if maskLen-readMask > 0 {
l, err = discard(r, maskLen-readMask)
read += l
if err != nil {
return read, err
}
}
return read, nil
}
if l, err = io.ReadFull(r, b[:8]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.UserMaskFeather = readFloat64(b, 0)
}
if maskParam&4 != 0 {
if maskLen-readMask < 1 {
// "vector mask density" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.VectorMaskDensity = int(b[0])
}
if maskParam&8 != 0 {
if maskLen-readMask < 8 {
// "vector mask feather" is not present.
if maskLen-readMask > 0 {
l, err = discard(r, maskLen-readMask)
read += l
if err != nil {
return read, err
}
}
return read, nil
}
if l, err = io.ReadFull(r, b[:8]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.VectorMaskFeather = readFloat64(b, 0)
}
}
if maskLen == 20 {
// Padding. Only present if size = 20.
if l, err = io.ReadFull(r, b[:2]); err != nil {
return read, err
}
read += l
readMask += l
return read, nil
}
if maskLen-readMask < 1 {
// "Real Flags" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.RealFlags = int(b[0])
if maskLen-readMask < 1 {
// "Real user mask background" is not present.
return read, nil
}
if l, err = io.ReadFull(r, b[:1]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.RealBackgroundColor = int(b[0])
if maskLen-readMask < 16 {
// "Rectangle enclosing layer mask" is not present.
if maskLen-readMask > 0 {
l, err = discard(r, maskLen-readMask)
read += l
if err != nil {
return read, err
}
}
return read, nil
}
if l, err = io.ReadFull(r, b[:16]); err != nil {
return read, err
}
read += l
readMask += l
layer.Mask.RealRect = image.Rect(
int(readUint32(b, 4)), int(readUint32(b, 0)),
int(readUint32(b, 12)), int(readUint32(b, 8)),
)
return read, nil
}
func readAdditionalLayerInfo(r io.Reader, infoLen int, cfg *Config, o *DecodeOptions) (infos map[AdditionalInfoKey][]byte, layers []Layer, read int, err error) {
if Debug != nil {
Debug.Println("start - additional layer info section")
Debug.Println(" infoLen:", infoLen)
}
infos = map[AdditionalInfoKey][]byte{}
b := make([]byte, 8)
var l int
for read < infoLen {
// Sometimes I encountered padded section and unpadded section,
// so find the signature to avoid failure.
b[0] = 0
for read < infoLen && b[0] != '8' {
if l, err = io.ReadFull(r, b[:1]); err != nil {
return nil, nil, read, err
}
read += l
}
if b[0] != '8' {
break
}
if l, err = io.ReadFull(r, b[1:]); err != nil {
return nil, nil, read, err
}
read += l
if sig := string(b[:4]); sig != sectionSignature && sig != "8B64" {
return nil, nil, read, errors.New("psd: unexpected the signature found in the additional layer information block")
}
key := AdditionalInfoKey(b[4:])
switch key {
case AdditionalInfoKeyLayerInfo,
AdditionalInfoKeyLayerInfo16,
AdditionalInfoKeyLayerInfo32:
if Debug != nil {
Debug.Println(" key:", key)
}
var layrs []Layer
if layrs, l, err = readLayerInfo(r, cfg, o); err != nil {
return nil, nil, read, err
}
read += l
layers = append(layers, layrs...)
default:
intSize := key.LenSize(cfg.PSB())
if l, err = io.ReadFull(r, b[:intSize]); err != nil {
return nil, nil, read, err
}
read += l
var data []byte
if ln := int(readUint(b, 0, intSize)); ln > 0 {
data = make([]byte, ln)
if l, err = io.ReadFull(r, data); err != nil {
return nil, nil, read, err
}
read += l
}
infos[key] = data
if Debug != nil {
Debug.Println(" key:", key, "dataLen:", len(data))
}
}
}
if infoLen != read {
return nil, nil, read, errors.New("psd: additional layer info read size mismatched. expected " + itoa(infoLen) + " actual " + itoa(read))
}
if Debug != nil {
Debug.Println("end - additional layer info section")
}
return infos, layers, read, nil
}

456
vendor/github.com/oov/psd/picker.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,456 @@
package psd
import (
"image"
"image/color"
psdColor "github.com/oov/psd/color"
)
type picker interface {
image.Image
setSource(rect image.Rectangle, src ...[]byte)
}
func findPicker(depth int, colorMode ColorMode, hasAlpha bool) picker {
switch colorMode {
case ColorModeBitmap, ColorModeGrayscale:
return findNGrayPicker(depth, hasAlpha)
case ColorModeRGB:
return findNRGBAPicker(depth, hasAlpha)
case ColorModeCMYK:
return findNCMYKAPicker(depth, hasAlpha)
}
return nil
}
func findGrayPicker(depth int) picker {
switch depth {
case 1:
return &pickerGray1{}
case 8:
return &pickerGray8{}
case 16:
return &pickerGray16{}
case 32:
return &pickerGray32{}
}
return nil
}
func findNGrayPicker(depth int, hasAlpha bool) picker {
switch depth {
case 8:
if hasAlpha {
return &pickerNGrayA8{}
}
return &pickerNGray8{}
case 16:
if hasAlpha {
return &pickerNGrayA16{}
}
return &pickerNGray16{}
case 32:
if hasAlpha {
return &pickerNGrayA32{}
}
return &pickerNGray32{}
}
return nil
}
func findNRGBAPicker(depth int, hasAlpha bool) picker {
switch depth {
case 8:
if hasAlpha {
return &pickerNRGBA8{}
}
return &pickerNRGB8{}
case 16:
if hasAlpha {
return &pickerNRGBA16{}
}
return &pickerNRGB16{}
case 32:
if hasAlpha {
return &pickerNRGBA32{}
}
return &pickerNRGB32{}
}
return nil
}
func findNCMYKAPicker(depth int, hasAlpha bool) picker {
switch depth {
case 8:
if hasAlpha {
return &pickerNCMYKA8{}
}
return &pickerNCMYK8{}
case 16:
if hasAlpha {
return &pickerNCMYKA16{}
}
return &pickerNCMYK16{}
}
return nil
}
type pickerPalette struct {
Rect image.Rectangle
Src []byte
Palette color.Palette
}
func (p *pickerPalette) setSource(rect image.Rectangle, src ...[]byte) { p.Rect, p.Src = rect, src[0] }
func (p *pickerPalette) ColorModel() color.Model { return p.Palette }
func (p *pickerPalette) Bounds() image.Rectangle { return p.Rect }
func (p *pickerPalette) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return p.Palette[p.Src[pos]]
}
type pickerGray1 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerGray1) setSource(rect image.Rectangle, src ...[]byte) { p.Rect, p.Y = rect, src[0] }
func (p *pickerGray1) ColorModel() color.Model { return psdColor.Gray1Model }
func (p *pickerGray1) Bounds() image.Rectangle { return p.Rect }
func (p *pickerGray1) At(x, y int) color.Color {
xx := x - p.Rect.Min.X
pos := (p.Rect.Dx()+7)>>3*(y-p.Rect.Min.Y) + xx>>3
return psdColor.Gray1{Y: p.Y[pos]&(1<<uint(^xx&7)) == 0}
}
type pickerGray8 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerGray8) setSource(rect image.Rectangle, src ...[]byte) { p.Rect, p.Y = rect, src[0] }
func (p *pickerGray8) ColorModel() color.Model { return color.GrayModel }
func (p *pickerGray8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerGray8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return color.Gray{Y: p.Y[pos]}
}
type pickerNGray8 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerNGray8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y = rect, src[0]
}
func (p *pickerNGray8) ColorModel() color.Model { return psdColor.NGrayAModel }
func (p *pickerNGray8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGray8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return psdColor.NGrayA{Y: p.Y[pos], A: 0xff}
}
type pickerNGrayA8 struct {
Rect image.Rectangle
Y, A []byte
}
func (p *pickerNGrayA8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y, p.A = rect, src[0], src[1]
}
func (p *pickerNGrayA8) ColorModel() color.Model { return psdColor.NGrayAModel }
func (p *pickerNGrayA8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGrayA8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return psdColor.NGrayA{Y: p.Y[pos], A: p.A[pos]}
}
type pickerGray16 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerGray16) setSource(rect image.Rectangle, src ...[]byte) { p.Rect, p.Y = rect, src[0] }
func (p *pickerGray16) ColorModel() color.Model { return color.Gray16Model }
func (p *pickerGray16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerGray16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return color.Gray16{Y: readUint16(p.Y, pos)}
}
type pickerNGray16 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerNGray16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y = rect, src[0]
}
func (p *pickerNGray16) ColorModel() color.Model { return psdColor.NGrayA32Model }
func (p *pickerNGray16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGray16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return psdColor.NGrayA32{Y: readUint16(p.Y, pos), A: 0xffff}
}
type pickerNGrayA16 struct {
Rect image.Rectangle
Y, A []byte
}
func (p *pickerNGrayA16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y, p.A = rect, src[0], src[1]
}
func (p *pickerNGrayA16) ColorModel() color.Model { return psdColor.NGrayA32Model }
func (p *pickerNGrayA16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGrayA16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return psdColor.NGrayA32{Y: readUint16(p.Y, pos), A: readUint16(p.A, pos)}
}
type pickerGray32 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerGray32) setSource(rect image.Rectangle, src ...[]byte) { p.Rect, p.Y = rect, src[0] }
func (p *pickerGray32) ColorModel() color.Model { return psdColor.Gray32Model }
func (p *pickerGray32) Bounds() image.Rectangle { return p.Rect }
func (p *pickerGray32) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 2
return psdColor.Gray32{Y: readFloat32(p.Y, pos)}
}
type pickerNGray32 struct {
Rect image.Rectangle
Y []byte
}
func (p *pickerNGray32) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y = rect, src[0]
}
func (p *pickerNGray32) ColorModel() color.Model { return psdColor.NGrayA64Model }
func (p *pickerNGray32) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGray32) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 2
return psdColor.NGrayA64{Y: readFloat32(p.Y, pos), A: 1}
}
type pickerNGrayA32 struct {
Rect image.Rectangle
Y, A []byte
}
func (p *pickerNGrayA32) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.Y, p.A = rect, src[0], src[1]
}
func (p *pickerNGrayA32) ColorModel() color.Model { return psdColor.NGrayA64Model }
func (p *pickerNGrayA32) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNGrayA32) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 2
return psdColor.NGrayA64{
Y: readFloat32(p.Y, pos),
A: readFloat32(p.A, pos),
}
}
type pickerNRGB8 struct {
Rect image.Rectangle
R, G, B []byte
}
func (p *pickerNRGB8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B = rect, src[0], src[1], src[2]
}
func (p *pickerNRGB8) ColorModel() color.Model { return color.NRGBAModel }
func (p *pickerNRGB8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGB8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return color.NRGBA{
R: p.R[pos],
G: p.G[pos],
B: p.B[pos],
A: 0xff,
}
}
type pickerNRGBA8 struct {
Rect image.Rectangle
R, G, B, A []byte
}
func (p *pickerNRGBA8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B, p.A = rect, src[0], src[1], src[2], src[3]
}
func (p *pickerNRGBA8) ColorModel() color.Model { return color.NRGBAModel }
func (p *pickerNRGBA8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGBA8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return color.NRGBA{p.R[pos], p.G[pos], p.B[pos], p.A[pos]}
}
type pickerNRGB16 struct {
Rect image.Rectangle
R, G, B []byte
}
func (p *pickerNRGB16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B = rect, src[0], src[1], src[2]
}
func (p *pickerNRGB16) ColorModel() color.Model { return color.NRGBA64Model }
func (p *pickerNRGB16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGB16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return color.NRGBA64{
R: readUint16(p.R, pos),
G: readUint16(p.G, pos),
B: readUint16(p.B, pos),
A: 0xffff,
}
}
type pickerNRGBA16 struct {
Rect image.Rectangle
R, G, B, A []byte
}
func (p *pickerNRGBA16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B, p.A = rect, src[0], src[1], src[2], src[3]
}
func (p *pickerNRGBA16) ColorModel() color.Model { return color.NRGBA64Model }
func (p *pickerNRGBA16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGBA16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return color.NRGBA64{
R: readUint16(p.R, pos),
G: readUint16(p.G, pos),
B: readUint16(p.B, pos),
A: readUint16(p.A, pos),
}
}
type pickerNRGB32 struct {
Rect image.Rectangle
R, G, B []byte
}
func (p *pickerNRGB32) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B = rect, src[0], src[1], src[2]
}
func (p *pickerNRGB32) ColorModel() color.Model { return psdColor.NRGBA128Model }
func (p *pickerNRGB32) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGB32) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 2
return psdColor.NRGBA128{
R: readFloat32(p.R, pos),
G: readFloat32(p.G, pos),
B: readFloat32(p.B, pos),
A: 1.0,
}
}
type pickerNRGBA32 struct {
Rect image.Rectangle
R, G, B, A []byte
}
func (p *pickerNRGBA32) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.R, p.G, p.B, p.A = rect, src[0], src[1], src[2], src[3]
}
func (p *pickerNRGBA32) ColorModel() color.Model { return psdColor.NRGBA128Model }
func (p *pickerNRGBA32) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNRGBA32) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 2
return psdColor.NRGBA128{
R: readFloat32(p.R, pos),
G: readFloat32(p.G, pos),
B: readFloat32(p.B, pos),
A: readFloat32(p.A, pos),
}
}
type pickerNCMYK8 struct {
Rect image.Rectangle
C, M, Y, K []byte
}
func (p *pickerNCMYK8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.C, p.M, p.Y, p.K = rect, src[0], src[1], src[2], src[3]
}
func (p *pickerNCMYK8) ColorModel() color.Model { return psdColor.NCMYKAModel }
func (p *pickerNCMYK8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNCMYK8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return psdColor.NCMYKA{
C: p.C[pos],
M: p.M[pos],
Y: p.Y[pos],
K: p.K[pos],
A: 0xff,
}
}
type pickerNCMYKA8 struct {
Rect image.Rectangle
C, M, Y, K, A []byte
}
func (p *pickerNCMYKA8) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.C, p.M, p.Y, p.K, p.A = rect, src[0], src[1], src[2], src[3], src[4]
}
func (p *pickerNCMYKA8) ColorModel() color.Model { return psdColor.NCMYKAModel }
func (p *pickerNCMYKA8) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNCMYKA8) At(x, y int) color.Color {
pos := (y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X
return psdColor.NCMYKA{
C: p.C[pos],
M: p.M[pos],
Y: p.Y[pos],
K: p.K[pos],
A: p.A[pos],
}
}
type pickerNCMYK16 struct {
Rect image.Rectangle
C, M, Y, K []byte
}
func (p *pickerNCMYK16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.C, p.M, p.Y, p.K = rect, src[0], src[1], src[2], src[3]
}
func (p *pickerNCMYK16) ColorModel() color.Model { return psdColor.NCMYKA80Model }
func (p *pickerNCMYK16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNCMYK16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return psdColor.NCMYKA80{
C: readUint16(p.C, pos),
M: readUint16(p.M, pos),
Y: readUint16(p.Y, pos),
K: readUint16(p.K, pos),
A: 0xffff,
}
}
type pickerNCMYKA16 struct {
Rect image.Rectangle
C, M, Y, K, A []byte
}
func (p *pickerNCMYKA16) setSource(rect image.Rectangle, src ...[]byte) {
p.Rect, p.C, p.M, p.Y, p.K, p.A = rect, src[0], src[1], src[2], src[3], src[4]
}
func (p *pickerNCMYKA16) ColorModel() color.Model { return psdColor.NCMYKA80Model }
func (p *pickerNCMYKA16) Bounds() image.Rectangle { return p.Rect }
func (p *pickerNCMYKA16) At(x, y int) color.Color {
pos := ((y-p.Rect.Min.Y)*p.Rect.Dx() + x - p.Rect.Min.X) << 1
return psdColor.NCMYKA80{
C: readUint16(p.C, pos),
M: readUint16(p.M, pos),
Y: readUint16(p.Y, pos),
K: readUint16(p.K, pos),
A: readUint16(p.A, pos),
}
}

313
vendor/github.com/oov/psd/psd.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,313 @@
package psd
import (
"errors"
"image"
"image/color"
"io"
)
// logger is subset of log.Logger.
type logger interface {
Printf(format string, v ...interface{})
Println(v ...interface{})
}
// Debug is useful for debugging.
//
// You can use by performing the following steps.
// psd.Debug = log.New(os.Stdout, "psd: ", log.Lshortfile)
var Debug logger
const (
headerSignature = "8BPS"
sectionSignature = "8BIM"
)
// AdditionalInfoKey represents the key of the additional layer information.
type AdditionalInfoKey string
// LenSize returns bytes of the length for this key.
func (a AdditionalInfoKey) LenSize(largeDocument bool) int {
if largeDocument {
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_71546
// (**PSB**, the following keys have a length count of 8 bytes:
// LMsk, Lr16, Lr32, Layr, Mt16, Mt32, Mtrn, Alph, FMsk, lnk2, FEid, FXid, PxSD.
switch a {
case "LMsk",
"Lr16",
"Lr32",
"Layr",
"Mt16",
"Mt32",
"Mtrn",
"Alph",
"FMsk",
"lnk2",
"FEid",
"FXid",
"PxSD":
return 8
}
}
return 4
}
// These keys are defined in this document.
//
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_71546
const (
AdditionalInfoKeyLayerInfo = AdditionalInfoKey("Layr")
AdditionalInfoKeyLayerInfo16 = AdditionalInfoKey("Lr16")
AdditionalInfoKeyLayerInfo32 = AdditionalInfoKey("Lr32")
AdditionalInfoKeyUnicodeLayerName = AdditionalInfoKey("luni")
AdditionalInfoKeyBlendClippingElements = AdditionalInfoKey("clbl")
AdditionalInfoKeySectionDividerSetting = AdditionalInfoKey("lsct")
AdditionalInfoKeySectionDividerSetting2 = AdditionalInfoKey("lsdk")
)
// Config represents Photoshop image file configuration.
type Config struct {
Version int
Rect image.Rectangle
Channels int
Depth int // 1 or 8 or 16 or 32
ColorMode ColorMode
ColorModeData []byte
Res map[int]ImageResource
}
// PSB returns whether image is large document format.
func (cfg *Config) PSB() bool {
return cfg.Version == 2
}
// Palette returns Palette if any.
func (cfg *Config) Palette() color.Palette {
if cfg.ColorMode != ColorModeIndexed {
return nil
}
// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_38034
// 0x0417(1046) | (Photoshop 6.0) Transparency Index.
// 2 bytes for the index of transparent color, if any.
transparentColorIndex := -1
if r, ok := cfg.Res[0x0417]; ok {
transparentColorIndex = int(readUint16(r.Data, 0))
}
pal := make(color.Palette, len(cfg.ColorModeData)/3)
for i := range pal {
c := color.NRGBA{
cfg.ColorModeData[i],
cfg.ColorModeData[i+256],
cfg.ColorModeData[i+512],
0xFF,
}
if i == transparentColorIndex {
c.A = 0
}
pal[i] = c
}
return pal
}
func (cfg *Config) makePicker() (picker, error) {
var pk picker
switch cfg.ColorMode {
case ColorModeIndexed:
pk = &pickerPalette{Palette: cfg.Palette()}
case ColorModeBitmap:
pk = &pickerGray1{}
default:
pk = findPicker(cfg.Depth, cfg.ColorMode, cfg.Channels > cfg.ColorMode.Channels() && hasAlphaID0(cfg.Res))
}
if pk == nil {
return nil, errors.New("psd: color mode " + itoa(int(cfg.ColorMode)) + " depth " + itoa(cfg.Depth) + " is not implemeted")
}
return pk, nil
}
// PSD represents Photoshop image file.
type PSD struct {
Config Config
Channel map[int]Channel
Layer []Layer
AdditinalLayerInfo map[AdditionalInfoKey][]byte
// Data is uncompressed merged image data.
Data []byte
Picker image.Image
}
// DecodeConfig returns the color model and dimensions of a image without decoding the entire image.
func DecodeConfig(r io.Reader) (cfg Config, read int, err error) {
const (
fileHeaderLen = 4 + 2 + 6 + 2 + 4 + 4 + 2 + 2
colorModeDataLen = 4
)
b := make([]byte, fileHeaderLen+colorModeDataLen)
var l int
if l, err = io.ReadFull(r, b); err != nil {
return Config{}, 0, err
}
read += l
if string(b[:4]) != headerSignature { // Signature
return Config{}, read, errors.New("psd: invalid format")
}
cfg.Version = int(readUint16(b, 4))
if cfg.Version != 1 && cfg.Version != 2 { // Version
return Config{}, read, errors.New("psd: unexpected file version: " + itoa(cfg.Version))
}
// b[6:12] Reserved
cfg.Channels = int(readUint16(b, 12))
if cfg.Channels < 1 || cfg.Channels > 56 {
return Config{}, read, errors.New("psd: unexpected the number of channels")
}
width, height := int(readUint32(b, 18)), int(readUint32(b, 14))
if height < 1 || (cfg.Version == 1 && height > 30000) || (cfg.Version == 2 && height > 300000) {
return Config{}, read, errors.New("psd: unexpected the height of the image")
}
if width < 1 || (cfg.Version == 1 && width > 30000) || (cfg.Version == 2 && width > 300000) {
return Config{}, read, errors.New("psd: unexpected the width of the image")
}
cfg.Rect = image.Rect(0, 0, width, height)
cfg.Depth = int(readUint16(b, 22))
if cfg.Depth != 1 && cfg.Depth != 8 && cfg.Depth != 16 && cfg.Depth != 32 {
return Config{}, read, errors.New("psd: unexpected color depth")
}
cfg.ColorMode = ColorMode(readUint16(b, 24))
if ln := readUint32(b, 26); ln > 0 {
cfg.ColorModeData = make([]byte, ln)
if l, err = io.ReadFull(r, cfg.ColorModeData); err != nil {
return Config{}, read, err
}
read += l
}
if Debug != nil {
Debug.Println("start - header")
Debug.Printf(" width: %d height: %d", width, height)
Debug.Printf(" channels: %d depth: %d colorMode %d", cfg.Channels, cfg.Depth, cfg.ColorMode)
Debug.Printf(" colorModeDataLen: %d", len(cfg.ColorModeData))
Debug.Println("end - header")
}
if cfg.Res, l, err = readImageResource(r); err != nil {
return Config{}, read, err
}
read += l
return cfg, read, nil
}
// DecodeOptions are the decoding options.
type DecodeOptions struct {
SkipLayerImage bool
SkipMergedImage bool
ConfigLoaded func(cfg Config) error
LayerImageLoaded func(layer *Layer, index int, total int)
}
// Decode reads a image from r and returns it.
// Default parameters are used if a nil *DecodeOptions is passed.
func Decode(r io.Reader, o *DecodeOptions) (psd *PSD, read int, err error) {
if o == nil {
o = &DecodeOptions{}
}
cfg, l, err := DecodeConfig(r)
if err != nil {
return nil, 0, err
}
read += l
if o.ConfigLoaded != nil {
err = o.ConfigLoaded(cfg)
if err != nil {
return nil, 0, err
}
}
psd, l, err = readLayerAndMaskInfo(r, &cfg, o)
if err != nil {
return nil, read, err
}
read += l
if !o.SkipMergedImage {
// allocate image buffer.
// `+7` and `>>3` is the padding for the 1bit depth color mode.
plane := (psd.Config.Rect.Dx()*psd.Config.Depth + 7) >> 3 * psd.Config.Rect.Dy()
psd.Data = make([]byte, plane*psd.Config.Channels)
chs := make([][]byte, psd.Config.Channels)
psd.Channel = make(map[int]Channel)
for i := 0; i < psd.Config.Channels; i++ {
data := psd.Data[plane*i : plane*(i+1) : plane*(i+1)]
chs[i] = data
pk := findGrayPicker(psd.Config.Depth)
pk.setSource(psd.Config.Rect, data)
psd.Channel[i] = Channel{
Data: data,
Picker: pk,
}
}
var pk picker
if pk, err = cfg.makePicker(); err != nil {
return nil, read, err
}
pk.setSource(psd.Config.Rect, chs...)
psd.Picker = pk
b := make([]byte, 2)
if l, err = io.ReadFull(r, b[:2]); err != nil {
return nil, read, err
}
read += l
cmpMethod := CompressionMethod(readUint16(b, 0))
l, err = cmpMethod.Decode(
psd.Data,
r,
0,
psd.Config.Rect,
psd.Config.Depth,
psd.Config.Channels,
psd.Config.PSB(),
)
if err != nil {
return nil, read, err
}
read += l
}
return psd, read, nil
}
func decode(r io.Reader) (image.Image, error) {
psd, _, err := Decode(r, &DecodeOptions{SkipLayerImage: true})
if err != nil {
return nil, err
}
return psd.Picker, nil
}
func decodeConfig(r io.Reader) (image.Config, error) {
cfg, _, err := DecodeConfig(r)
if err != nil {
return image.Config{}, err
}
var pk picker
if pk, err = cfg.makePicker(); err != nil {
return image.Config{}, err
}
return image.Config{
Width: cfg.Rect.Dx(),
Height: cfg.Rect.Dy(),
ColorModel: pk.ColorModel(),
}, nil
}
func init() {
image.RegisterFormat("psd", headerSignature+"\x00\x01", decode, decodeConfig)
image.RegisterFormat("psb", headerSignature+"\x00\x02", decode, decodeConfig)
}

156
vendor/github.com/oov/psd/util.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,156 @@
package psd
import (
"io"
"math"
"unicode/utf16"
)
func itoa(x int) string {
var b [32]byte
var minus bool
if x < 0 {
minus = true
x = -x
}
i := len(b) - 1
for x > 9 {
b[i] = byte(x%10 + '0')
x /= 10
i--
}
b[i] = byte(x + '0')
if minus {
i--
b[i] = '-'
}
return string(b[i:])
}
func readUint16(b []byte, offset int) uint16 {
return uint16(b[offset])<<8 | uint16(b[offset+1])
}
func writeUint16(b []byte, v uint16, offset int) {
b[offset] = uint8(v >> 8)
b[offset+1] = uint8(v)
}
func readUint32(b []byte, offset int) uint32 {
return uint32(b[offset])<<24 | uint32(b[offset+1])<<16 | uint32(b[offset+2])<<8 | uint32(b[offset+3])
}
func readUint64(b []byte, offset int) uint64 {
return uint64(b[offset])<<56 | uint64(b[offset+1])<<48 | uint64(b[offset+2])<<40 | uint64(b[offset+3])<<32 |
uint64(b[offset+4])<<24 | uint64(b[offset+5])<<16 | uint64(b[offset+6])<<8 | uint64(b[offset+7])
}
func get4or8(is64 bool) int {
if is64 {
return 8
}
return 4
}
func readUint(b []byte, offset int, size int) uint64 {
switch size {
case 8:
return readUint64(b, offset)
case 4:
return uint64(readUint32(b, offset))
case 2:
return uint64(readUint16(b, offset))
case 1:
return uint64(b[offset])
}
panic("psd: unexpected size")
}
func readFloat32(b []byte, offset int) float32 {
return math.Float32frombits(readUint32(b, offset))
}
func readFloat64(b []byte, offset int) float64 {
return math.Float64frombits(readUint64(b, offset))
}
func writeUint32(b []byte, v uint32, offset int) {
b[offset] = uint8(v >> 24)
b[offset+1] = uint8(v >> 16)
b[offset+2] = uint8(v >> 8)
b[offset+3] = uint8(v)
}
func readUnicodeString(b []byte) string {
ln := readUint32(b, 0)
if ln == 0 {
return ""
}
buf := make([]uint16, ln)
for i := range buf {
buf[i] = readUint16(b, 4+i<<1)
}
return string(utf16.Decode(buf))
}
func adjustAlign2(r io.Reader, l int) (read int, err error) {
if l&1 != 0 {
var b [1]byte
return r.Read(b[:])
}
return 0, nil
}
func adjustAlign4(r io.Reader, l int) (read int, err error) {
if gap := l & 3; gap > 0 {
var b [4]byte
return r.Read(b[:4-gap])
}
return 0, nil
}
func discard(r io.Reader, skip int) (read int, err error) {
type discarder interface {
Discard(n int) (discarded int, err error)
}
switch rr := r.(type) {
case discarder:
return rr.Discard(skip)
case io.Seeker:
if _, err = rr.Seek(int64(skip), 1); err != nil {
return 0, err
}
return skip, nil
default:
return io.ReadFull(r, make([]byte, skip))
}
}
func readPascalString(r io.Reader) (str string, read int, err error) {
b := make([]byte, 1)
if _, err := io.ReadFull(r, b); err != nil {
return "", 0, err
}
if b[0] == 0 {
return "", 1, nil
}
buf := make([]byte, b[0])
if _, err := io.ReadFull(r, buf); err != nil {
return "", 1, err
}
return string(buf), len(buf) + 1, nil
}
func reportReaderPosition(format string, r io.Reader) error {
sk, ok := r.(io.Seeker)
if !ok {
return nil
}
pos, err := sk.Seek(0, 1)
if err != nil {
return err
}
Debug.Printf(format, pos)
return nil
}

6
vendor/modules.txt поставляемый
Просмотреть файл

@@ -159,6 +159,8 @@ github.com/google/btree
# github.com/google/uuid v1.1.1
## explicit
github.com/google/uuid
# github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99
github.com/gopherjs/gopherjs/js
# github.com/gorilla/handlers v1.4.2
## explicit
github.com/gorilla/handlers
@@ -360,6 +362,10 @@ github.com/olivere/elastic/uritemplates
## explicit
# github.com/onsi/gomega v1.9.0
## explicit
# github.com/oov/psd v0.0.0-20200705094106-99303fb2511f
## explicit
github.com/oov/psd
github.com/oov/psd/color
# github.com/opentracing/opentracing-go v1.1.0
## explicit
github.com/opentracing/opentracing-go