photoshop.go 1.3 KB

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