func main() { if len(os.Args) < 2 { fmt.Printf("USAGE: %s psdfile", os.Args[0]) return } file, err := os.Open(os.Args[1]) 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) } } }
func parse(rd readerAt, progress func(progress float64), makeCanvas func(seqID int, layer *psd.Layer)) (*root, error) { var r root s := time.Now().UnixNano() if rd.Size() < 4 { return nil, errors.New("unsupported file type") } var head [4]byte if _, err := rd.ReadAt(head[:], 0); err != nil { return nil, err } var psdReader *genericProgressReader switch string(head[:]) { case "PK\x03\x04": // zip archive zr, err := zip.NewReader(rd, rd.Size()) if err != nil { return nil, err } var psdf, pfvf, txtf *zip.File for _, f := range zr.File { if psdf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".psd" { psdf = f continue } if psdf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".psb" { psdf = f continue } if pfvf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".pfv" { pfvf = f continue } if txtf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".txt" { txtf = f continue } } if psdf == nil { return nil, errors.New("psd file is not found from given zip archive") } if pfvf != nil { var pfvr io.ReadCloser pfvr, err = pfvf.Open() if err != nil { return nil, err } defer pfvr.Close() r.PFVModDate = pfvf.ModTime().Unix() r.PFV, err = readTextFile(pfvr) if err != nil { return nil, err } } if txtf != nil { var txtr io.ReadCloser txtr, err = txtf.Open() if err != nil { return nil, err } defer txtr.Close() r.Readme, err = readTextFile(txtr) if err != nil { return nil, err } } rc, err := zipFileOpenFast(rd, psdf, 1024*1024*100) if err != nil { return nil, err } defer rc.Close() psdReader = &genericProgressReader{ R: rc, Hash: md5.New(), Progress: progress, size: int(psdf.UncompressedSize64), } case "7z\xbc\xaf": // 7z archive return nil, errors.New("7z archive is not supported") case "8BPS": // psd file psdReader = &genericProgressReader{ R: bufio.NewReaderSize(rd, 1024*1024*2), Hash: md5.New(), Progress: progress, size: int(rd.Size()), } break default: return nil, errors.New("unsupported file type") } psdImg, _, err := psd.Decode(psdReader, &psd.DecodeOptions{ LayerImageLoaded: func(layer *psd.Layer, index int, total int) { makeCanvas(index, layer) layer.Picker = nil layer.Channel = nil }, SkipMergedImage: true, }) if err != nil { return nil, err } e := time.Now().UnixNano() progress(1) log.Println("decode PSD structure:", (e-s)/1e6) if psdImg.Config.ColorMode != psd.ColorModeRGB { return nil, errors.New("Unsupported color mode") } s = time.Now().UnixNano() r.Hash = fmt.Sprintf("%x", psdReader.Sum()) if err = r.Build(psdImg); err != nil { return nil, err } e = time.Now().UnixNano() log.Println("build layer tree:", (e-s)/1e6) return &r, nil }