12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- package photoshop
- import (
- "bytes"
- "encoding/binary"
- "errors"
- )
- var (
- ps3Header = []byte("Photoshop 3.0\x00")
- ps3BlockHeader = []byte("8BIM")
- errInvalidPS3Header = errors.New("invalid Photoshop 3.0 header")
- )
- const (
- IptcKey = "\x04\x04"
- ResolutionKey = "\x03\xed"
- )
- type PhotoshopMap map[string][]byte
- func Parse(data []byte, m PhotoshopMap) error {
- buf := bytes.NewBuffer(data)
- if !bytes.Equal(buf.Next(14), ps3Header) {
- return errInvalidPS3Header
- }
- // Read blocks
- // Minimal block size is 12 (4 blockHeader + 2 resoureceID + 2 name + 4 blockSize)
- for buf.Len() >= 12 {
- if !bytes.Equal(buf.Bytes()[:4], ps3BlockHeader) {
- buf.Next(1)
- continue
- }
- // Skip block header
- buf.Next(4)
- resoureceID := buf.Next(2)
- // Skip name
- // Name is zero terminated string padded to even
- for buf.Len() > 0 && buf.Next(2)[1] != 0 {
- }
- if buf.Len() < 4 {
- break
- }
- blockSize := int(binary.BigEndian.Uint32(buf.Next(4)))
- if buf.Len() < blockSize {
- break
- }
- blockData := buf.Next(blockSize)
- m[string(resoureceID)] = blockData
- }
- return nil
- }
- func (m PhotoshopMap) Dump() []byte {
- buf := new(bytes.Buffer)
- buf.Grow(26)
- buf.Write(ps3Header)
- for id, data := range m {
- if len(data) == 0 {
- continue
- }
- buf.Write(ps3BlockHeader)
- buf.WriteString(id)
- // Write empty name
- buf.Write([]byte{0, 0})
- binary.Write(buf, binary.BigEndian, uint32(len(data)))
- buf.Write(data)
- }
- return buf.Bytes()
- }
|