photoshop.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package photoshop
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. )
  7. var (
  8. ps3Header = []byte("Photoshop 3.0\x00")
  9. ps3BlockHeader = []byte("8BIM")
  10. errInvalidPS3Header = errors.New("invalid Photoshop 3.0 header")
  11. )
  12. const (
  13. IptcKey = "\x04\x04"
  14. ResolutionKey = "\x03\xed"
  15. )
  16. type PhotoshopMap map[string][]byte
  17. func Parse(data []byte, m PhotoshopMap) error {
  18. buf := bytes.NewBuffer(data)
  19. if !bytes.Equal(buf.Next(14), ps3Header) {
  20. return errInvalidPS3Header
  21. }
  22. // Read blocks
  23. // Minimal block size is 12 (4 blockHeader + 2 resoureceID + 2 name + 4 blockSize)
  24. for buf.Len() >= 12 {
  25. if !bytes.Equal(buf.Bytes()[:4], ps3BlockHeader) {
  26. buf.Next(1)
  27. continue
  28. }
  29. // Skip block header
  30. buf.Next(4)
  31. resoureceID := buf.Next(2)
  32. // Skip name
  33. // Name is zero terminated string padded to even
  34. for buf.Len() > 0 && buf.Next(2)[1] != 0 {
  35. }
  36. if buf.Len() < 4 {
  37. break
  38. }
  39. blockSize := int(binary.BigEndian.Uint32(buf.Next(4)))
  40. if buf.Len() < blockSize {
  41. break
  42. }
  43. blockData := buf.Next(blockSize)
  44. m[string(resoureceID)] = blockData
  45. }
  46. return nil
  47. }
  48. func (m PhotoshopMap) Dump() []byte {
  49. buf := new(bytes.Buffer)
  50. buf.Grow(26)
  51. buf.Write(ps3Header)
  52. for id, data := range m {
  53. if len(data) == 0 {
  54. continue
  55. }
  56. buf.Write(ps3BlockHeader)
  57. buf.WriteString(id)
  58. // Write empty name
  59. buf.Write([]byte{0, 0})
  60. binary.Write(buf, binary.BigEndian, uint32(len(data)))
  61. buf.Write(data)
  62. }
  63. return buf.Bytes()
  64. }